mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-04-30 14:44:27 +02:00
Properly check for different author and show it as a warning when the author has changed. Properly show signature warnings when installing a script.
This commit is contained in:
parent
f19b7fa584
commit
1531a558a5
@ -42,7 +42,8 @@ class AddSourceActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private val _client = ManagedHttpClient();
|
private val _client = ManagedHttpClient();
|
||||||
|
|
||||||
private var _config : SourcePluginConfig? = null;
|
private var _config: SourcePluginConfig? = null;
|
||||||
|
private var _script: String? = null;
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@ -81,7 +82,7 @@ class AddSourceActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
_buttonInstall.setOnClickListener {
|
_buttonInstall.setOnClickListener {
|
||||||
_config?.let {
|
_config?.let {
|
||||||
install(_config!!);
|
install(_config!!, _script!!);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -114,6 +115,7 @@ class AddSourceActivity : AppCompatActivity() {
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
val config: SourcePluginConfig;
|
||||||
try {
|
try {
|
||||||
val configResp = _client.get(url);
|
val configResp = _client.get(url);
|
||||||
if(!configResp.isOk)
|
if(!configResp.isOk)
|
||||||
@ -121,33 +123,51 @@ class AddSourceActivity : AppCompatActivity() {
|
|||||||
val configJson = configResp.body?.string();
|
val configJson = configResp.body?.string();
|
||||||
if(configJson.isNullOrEmpty())
|
if(configJson.isNullOrEmpty())
|
||||||
throw IllegalStateException("No response");
|
throw IllegalStateException("No response");
|
||||||
val config = SourcePluginConfig.fromJson(configJson, url);
|
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
config = SourcePluginConfig.fromJson(configJson, url);
|
||||||
loadConfig(config);
|
} catch(ex: SerializationException) {
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(ex: SerializationException) {
|
|
||||||
Logger.e(TAG, "Failed decode config", ex);
|
Logger.e(TAG, "Failed decode config", ex);
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
UIDialogs.showDialog(this@AddSourceActivity, R.drawable.ic_error,
|
UIDialogs.showDialog(this@AddSourceActivity, R.drawable.ic_error,
|
||||||
"Invalid Config Format", null, null,
|
"Invalid Config Format", null, null,
|
||||||
0, UIDialogs.Action("Ok", { finish() }, UIDialogs.ActionStyle.PRIMARY));
|
0, UIDialogs.Action("Ok", { finish() }, UIDialogs.ActionStyle.PRIMARY));
|
||||||
};
|
};
|
||||||
}
|
return@launch;
|
||||||
catch(ex: Exception) {
|
} catch(ex: Exception) {
|
||||||
Logger.e(TAG, "Failed fetch config", ex);
|
Logger.e(TAG, "Failed fetch config", ex);
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
UIDialogs.showGeneralErrorDialog(this@AddSourceActivity, "Failed to fetch configuration", ex);
|
UIDialogs.showGeneralErrorDialog(this@AddSourceActivity, "Failed to fetch configuration", ex);
|
||||||
};
|
};
|
||||||
|
return@launch;
|
||||||
|
}
|
||||||
|
|
||||||
|
val script: String?
|
||||||
|
try {
|
||||||
|
val scriptResp = _client.get(config.absoluteScriptUrl);
|
||||||
|
if (!scriptResp.isOk)
|
||||||
|
throw IllegalStateException("script not available [${scriptResp.code}]");
|
||||||
|
script = scriptResp.body?.string();
|
||||||
|
if (script.isNullOrEmpty())
|
||||||
|
throw IllegalStateException("script empty");
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
Logger.e(TAG, "Failed fetch script", ex);
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
UIDialogs.showGeneralErrorDialog(this@AddSourceActivity, "Failed to fetch script", ex);
|
||||||
|
};
|
||||||
|
return@launch;
|
||||||
|
}
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
loadConfig(config, script);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadConfig(config: SourcePluginConfig) {
|
private fun loadConfig(config: SourcePluginConfig, script: String) {
|
||||||
_config = config;
|
_config = config;
|
||||||
|
_script = script;
|
||||||
|
|
||||||
_sourceHeader.loadConfig(config);
|
_sourceHeader.loadConfig(config, script);
|
||||||
_sourcePermissions.removeAllViews();
|
_sourcePermissions.removeAllViews();
|
||||||
_sourceWarnings.removeAllViews();
|
_sourceWarnings.removeAllViews();
|
||||||
|
|
||||||
@ -171,7 +191,7 @@ class AddSourceActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
val pastelRed = resources.getColor(R.color.pastel_red);
|
val pastelRed = resources.getColor(R.color.pastel_red);
|
||||||
|
|
||||||
for(warning in config.getWarnings())
|
for(warning in config.getWarnings(script))
|
||||||
_sourceWarnings.addView(
|
_sourceWarnings.addView(
|
||||||
SourceInfoView(this,
|
SourceInfoView(this,
|
||||||
R.drawable.ic_security_pred,
|
R.drawable.ic_security_pred,
|
||||||
@ -182,8 +202,8 @@ class AddSourceActivity : AppCompatActivity() {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
fun install(config: SourcePluginConfig) {
|
fun install(config: SourcePluginConfig, script: String) {
|
||||||
StatePlugins.instance.installPlugin(this, lifecycleScope, config) {
|
StatePlugins.instance.installPlugin(this, lifecycleScope, config, script) {
|
||||||
if(it)
|
if(it)
|
||||||
backToSources();
|
backToSources();
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import android.net.Uri
|
|||||||
import com.futo.platformplayer.SignatureProvider
|
import com.futo.platformplayer.SignatureProvider
|
||||||
import com.futo.platformplayer.api.media.Serializer
|
import com.futo.platformplayer.api.media.Serializer
|
||||||
import com.futo.platformplayer.engine.IV8PluginConfig
|
import com.futo.platformplayer.engine.IV8PluginConfig
|
||||||
|
import com.futo.platformplayer.states.StatePlugins
|
||||||
import kotlinx.serialization.decodeFromString
|
import kotlinx.serialization.decodeFromString
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -78,6 +79,15 @@ class SourcePluginConfig(
|
|||||||
fun getWarnings(scriptToCheck: String? = null) : List<Pair<String,String>> {
|
fun getWarnings(scriptToCheck: String? = null) : List<Pair<String,String>> {
|
||||||
val list = mutableListOf<Pair<String,String>>();
|
val list = mutableListOf<Pair<String,String>>();
|
||||||
|
|
||||||
|
val currentlyInstalledPlugin = StatePlugins.instance.getPlugin(id);
|
||||||
|
if (currentlyInstalledPlugin != null) {
|
||||||
|
if (currentlyInstalledPlugin.config.scriptPublicKey != scriptPublicKey) {
|
||||||
|
list.add(Pair(
|
||||||
|
"Different Author",
|
||||||
|
"This plugin was signed by a different author. Please ensure that this is correct and that the plugin was not provided by a malicious actor."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(scriptPublicKey.isNullOrEmpty() || scriptSignature.isNullOrEmpty())
|
if(scriptPublicKey.isNullOrEmpty() || scriptSignature.isNullOrEmpty())
|
||||||
list.add(Pair(
|
list.add(Pair(
|
||||||
"Missing Signature",
|
"Missing Signature",
|
||||||
|
@ -185,7 +185,7 @@ class SourceDetailFragment : MainFragment() {
|
|||||||
val config = _config;
|
val config = _config;
|
||||||
|
|
||||||
if (config != null) {
|
if (config != null) {
|
||||||
_sourceHeader.loadConfig(config);
|
_sourceHeader.loadConfig(config, StatePlugins.instance.getScript(config.id));
|
||||||
} else {
|
} else {
|
||||||
_sourceHeader.clear();
|
_sourceHeader.clear();
|
||||||
}
|
}
|
||||||
|
@ -177,18 +177,16 @@ class StatePlugins {
|
|||||||
}
|
}
|
||||||
fun installPlugin(context: Context, scope: CoroutineScope, sourceUrl: String, handler: ((Boolean) -> Unit)? = null) {
|
fun installPlugin(context: Context, scope: CoroutineScope, sourceUrl: String, handler: ((Boolean) -> Unit)? = null) {
|
||||||
scope.launch(Dispatchers.IO) {
|
scope.launch(Dispatchers.IO) {
|
||||||
|
val client = ManagedHttpClient();
|
||||||
|
val config: SourcePluginConfig;
|
||||||
try {
|
try {
|
||||||
val configResp = ManagedHttpClient().get(sourceUrl);
|
val configResp = client.get(sourceUrl);
|
||||||
if(!configResp.isOk)
|
if(!configResp.isOk)
|
||||||
throw IllegalStateException("Failed request with ${configResp.code}");
|
throw IllegalStateException("Failed request with ${configResp.code}");
|
||||||
val configJson = configResp.body?.string();
|
val configJson = configResp.body?.string();
|
||||||
if(configJson.isNullOrEmpty())
|
if(configJson.isNullOrEmpty())
|
||||||
throw IllegalStateException("No response");
|
throw IllegalStateException("No response");
|
||||||
val config = SourcePluginConfig.fromJson(configJson, sourceUrl);
|
config = SourcePluginConfig.fromJson(configJson, sourceUrl);
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
installPlugin(context, scope, config, handler);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch(ex: SerializationException) {
|
catch(ex: SerializationException) {
|
||||||
Logger.e(TAG, "Failed decode config", ex);
|
Logger.e(TAG, "Failed decode config", ex);
|
||||||
@ -199,8 +197,8 @@ class StatePlugins {
|
|||||||
finish();
|
finish();
|
||||||
handler?.invoke(false);
|
handler?.invoke(false);
|
||||||
}, UIDialogs.ActionStyle.PRIMARY));
|
}, UIDialogs.ActionStyle.PRIMARY));
|
||||||
|
|
||||||
};
|
};
|
||||||
|
return@launch;
|
||||||
}
|
}
|
||||||
catch(ex: Exception) {
|
catch(ex: Exception) {
|
||||||
Logger.e(TAG, "Failed fetch config", ex);
|
Logger.e(TAG, "Failed fetch config", ex);
|
||||||
@ -209,13 +207,36 @@ class StatePlugins {
|
|||||||
handler?.invoke(false);
|
handler?.invoke(false);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
return@launch;
|
||||||
|
}
|
||||||
|
|
||||||
|
val script: String?
|
||||||
|
try {
|
||||||
|
val scriptResp = client.get(config.absoluteScriptUrl);
|
||||||
|
if (!scriptResp.isOk)
|
||||||
|
throw IllegalStateException("script not available [${scriptResp.code}]");
|
||||||
|
script = scriptResp.body?.string();
|
||||||
|
if (script.isNullOrEmpty())
|
||||||
|
throw IllegalStateException("script empty");
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
Logger.e(TAG, "Failed fetch script", ex);
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
UIDialogs.showGeneralErrorDialog(context, "Failed to fetch script", ex);
|
||||||
|
};
|
||||||
|
return@launch;
|
||||||
|
}
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
installPlugin(context, scope, config, script, handler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun installPlugin(context: Context, scope: CoroutineScope, config: SourcePluginConfig, handler: ((Boolean)->Unit)? = null) {
|
fun installPlugin(context: Context, scope: CoroutineScope, config: SourcePluginConfig, script: String, handler: ((Boolean)->Unit)? = null) {
|
||||||
val client = ManagedHttpClient();
|
val client = ManagedHttpClient();
|
||||||
val warnings = config.getWarnings();
|
val warnings = config.getWarnings();
|
||||||
|
|
||||||
|
if (script.isEmpty())
|
||||||
|
throw IllegalStateException("script empty");
|
||||||
|
|
||||||
fun doInstall(reinstall: Boolean) {
|
fun doInstall(reinstall: Boolean) {
|
||||||
UIDialogs.showDialogProgress(context) {
|
UIDialogs.showDialogProgress(context) {
|
||||||
@ -224,13 +245,6 @@ class StatePlugins {
|
|||||||
|
|
||||||
scope.launch(Dispatchers.IO) {
|
scope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val scriptResp = client.get(config.absoluteScriptUrl);
|
|
||||||
if (!scriptResp.isOk)
|
|
||||||
throw IllegalStateException("script not available [${scriptResp.code}]");
|
|
||||||
val script = scriptResp.body?.string();
|
|
||||||
if (script.isNullOrEmpty())
|
|
||||||
throw IllegalStateException("script empty");
|
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
it.setText("Validating script...");
|
it.setText("Validating script...");
|
||||||
it.setProgress(0.25);
|
it.setProgress(0.25);
|
||||||
|
@ -55,7 +55,7 @@ class SourceHeaderView : LinearLayout {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadConfig(config: SourcePluginConfig) {
|
fun loadConfig(config: SourcePluginConfig, script: String?) {
|
||||||
_config = config;
|
_config = config;
|
||||||
|
|
||||||
val loadedIcon = StatePlugins.instance.getPluginIconOrNull(config.id);
|
val loadedIcon = StatePlugins.instance.getPluginIconOrNull(config.id);
|
||||||
@ -80,8 +80,10 @@ class SourceHeaderView : LinearLayout {
|
|||||||
_sourceBy.setTextColor(Color.WHITE);
|
_sourceBy.setTextColor(Color.WHITE);
|
||||||
|
|
||||||
if (!config.scriptPublicKey.isNullOrEmpty() && !config.scriptSignature.isNullOrEmpty()) {
|
if (!config.scriptPublicKey.isNullOrEmpty() && !config.scriptSignature.isNullOrEmpty()) {
|
||||||
val script = StatePlugins.instance.getScript(config.id);
|
if (script == null) {
|
||||||
if (script != null && config.validate(script)) {
|
_sourceSignature.setTextColor(Color.rgb(0xAC, 0xAC, 0xAC));
|
||||||
|
_sourceSignature.text = "Script is not available";
|
||||||
|
} else if (config.validate(script)) {
|
||||||
_sourceSignature.setTextColor(Color.rgb(0, 255, 0));
|
_sourceSignature.setTextColor(Color.rgb(0, 255, 0));
|
||||||
_sourceSignature.text = "Signature is valid";
|
_sourceSignature.text = "Signature is valid";
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user