mirror of https://github.com/ospab/ostp.git
Compare commits
2 Commits
bc61b47817
...
cf14a4243c
| Author | SHA1 | Date |
|---|---|---|
|
|
cf14a4243c | |
|
|
66368c9d0f |
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"target_version": "0.4.3",
|
"target_version": "0.4.4",
|
||||||
"branch": "master",
|
"branch": "master",
|
||||||
"alpha_iteration": 0,
|
"alpha_iteration": 0,
|
||||||
"beta_iteration": 4
|
"beta_iteration": 0
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1386,7 +1386,7 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ostp"
|
name = "ostp"
|
||||||
version = "0.4.3"
|
version = "0.4.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64",
|
"base64",
|
||||||
|
|
@ -1409,7 +1409,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ostp-client"
|
name = "ostp-client"
|
||||||
version = "0.4.3"
|
version = "0.4.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64",
|
"base64",
|
||||||
|
|
@ -1440,7 +1440,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ostp-core"
|
name = "ostp-core"
|
||||||
version = "0.4.3"
|
version = "0.4.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
|
@ -1474,7 +1474,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ostp-server"
|
name = "ostp-server"
|
||||||
version = "0.4.3"
|
version = "0.4.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"axum",
|
"axum",
|
||||||
|
|
@ -1507,7 +1507,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ostp-tun"
|
name = "ostp-tun"
|
||||||
version = "0.4.3"
|
version = "0.4.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"libc",
|
"libc",
|
||||||
|
|
@ -1519,7 +1519,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ostp-tun-helper"
|
name = "ostp-tun-helper"
|
||||||
version = "0.4.3"
|
version = "0.4.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ resolver = "2"
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
version = "0.4.3"
|
version = "0.4.4"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 0.4.3+30
|
version: 0.4.4+31
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.11.4
|
sdk: ^3.11.4
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "ostp-gui",
|
"name": "ostp-gui",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.4.3",
|
"version": "0.4.4",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"tauri": "tauri",
|
"tauri": "tauri",
|
||||||
|
|
|
||||||
|
|
@ -2665,7 +2665,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ostp-client"
|
name = "ostp-client"
|
||||||
version = "0.4.3"
|
version = "0.4.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
|
|
@ -2696,7 +2696,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ostp-core"
|
name = "ostp-core"
|
||||||
version = "0.4.3"
|
version = "0.4.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
|
@ -2713,7 +2713,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ostp-gui"
|
name = "ostp-gui"
|
||||||
version = "0.4.3"
|
version = "0.4.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"json_comments",
|
"json_comments",
|
||||||
|
|
@ -2733,7 +2733,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ostp-tun"
|
name = "ostp-tun"
|
||||||
version = "0.4.3"
|
version = "0.4.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"libc",
|
"libc",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "ostp-gui"
|
name = "ostp-gui"
|
||||||
version = "0.4.3"
|
version = "0.4.4"
|
||||||
description = "OSTP desktop GUI"
|
description = "OSTP desktop GUI"
|
||||||
authors = ["ospab"]
|
authors = ["ospab"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
|
||||||
|
|
@ -849,14 +849,74 @@ fn xml_escape(s: &str) -> String {
|
||||||
.replace('\'', "'")
|
.replace('\'', "'")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the elevated-launch Scheduled Task already exists.
|
/// Reverse of [`xml_escape`]. `&` must be undone last or `<` would
|
||||||
|
/// come back as `<`.
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
fn helper_task_exists() -> bool {
|
fn xml_unescape(s: &str) -> String {
|
||||||
quiet_command("schtasks")
|
s.replace(""", "\"")
|
||||||
.args(["/Query", "/TN", HELPER_TASK_NAME])
|
.replace("'", "'")
|
||||||
|
.replace("<", "<")
|
||||||
|
.replace(">", ">")
|
||||||
|
.replace("&", "&")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The exe path currently baked into the registered task, if any.
|
||||||
|
///
|
||||||
|
/// Queried as XML rather than `/FO LIST /V`: the list format's field labels are
|
||||||
|
/// localized (on a Russian Windows "Task To Run" is "Задача для запуска"),
|
||||||
|
/// whereas XML tag names are fixed. schtasks writes UTF-16LE with a BOM here,
|
||||||
|
/// but tolerate UTF-8 in case that ever changes.
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
fn helper_task_command() -> Option<String> {
|
||||||
|
let out = quiet_command("schtasks")
|
||||||
|
.args(["/Query", "/TN", HELPER_TASK_NAME, "/XML"])
|
||||||
.output()
|
.output()
|
||||||
.map(|o| o.status.success())
|
.ok()?;
|
||||||
.unwrap_or(false)
|
if !out.status.success() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let text = if out.stdout.starts_with(&[0xFF, 0xFE]) {
|
||||||
|
let units: Vec<u16> = out.stdout[2..]
|
||||||
|
.chunks_exact(2)
|
||||||
|
.map(|c| u16::from_le_bytes([c[0], c[1]]))
|
||||||
|
.collect();
|
||||||
|
String::from_utf16_lossy(&units)
|
||||||
|
} else {
|
||||||
|
String::from_utf8_lossy(&out.stdout).into_owned()
|
||||||
|
};
|
||||||
|
|
||||||
|
let start = text.find("<Command>")? + "<Command>".len();
|
||||||
|
let end = text[start..].find("</Command>")? + start;
|
||||||
|
Some(xml_unescape(text[start..end].trim()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether a task is registered AND still points at the exe we are about to run.
|
||||||
|
///
|
||||||
|
/// The path matters as much as the name. A task registered by a dev build (or
|
||||||
|
/// by an install that has since moved) keeps its original `<Command>`, and
|
||||||
|
/// `schtasks /Run` reports success merely for *accepting* the request — a task
|
||||||
|
/// whose exe no longer exists fails asynchronously and silently. Trusting the
|
||||||
|
/// name alone therefore bought a 60-second "Timeout connecting to helper" on
|
||||||
|
/// every single connect, permanently, until the task was deleted by hand.
|
||||||
|
/// Re-registering costs one consent prompt and fixes it for good.
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
fn helper_task_matches(exe: &std::path::Path) -> bool {
|
||||||
|
let Some(registered) = helper_task_command() else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let registered = registered.trim().trim_matches('"');
|
||||||
|
|
||||||
|
// Canonicalize both sides when possible so `..`, short 8.3 names and
|
||||||
|
// casing differences do not read as a mismatch. A missing file cannot be
|
||||||
|
// canonicalized — which is itself a mismatch worth re-registering over.
|
||||||
|
match (
|
||||||
|
std::fs::canonicalize(registered),
|
||||||
|
std::fs::canonicalize(exe),
|
||||||
|
) {
|
||||||
|
(Ok(a), Ok(b)) => a == b,
|
||||||
|
_ => registered.eq_ignore_ascii_case(&exe.display().to_string()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register the Scheduled Task. This is the ONLY step that needs elevation, and
|
/// Register the Scheduled Task. This is the ONLY step that needs elevation, and
|
||||||
|
|
@ -966,10 +1026,10 @@ fn install_helper_task(exe: &std::path::Path) -> anyhow::Result<()> {
|
||||||
Err(e) => anyhow::bail!("could not run powershell to register the task: {e}"),
|
Err(e) => anyhow::bail!("could not run powershell to register the task: {e}"),
|
||||||
}
|
}
|
||||||
|
|
||||||
if helper_task_exists() {
|
if helper_task_matches(exe) {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
anyhow::bail!("schtasks reported success but the task is not present")
|
anyhow::bail!("schtasks reported success but the task does not point at {}", exe.display())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -994,12 +1054,12 @@ fn launch_as_admin(exe: &std::path::PathBuf, token: &str, port: u16) -> anyhow::
|
||||||
let wrote_args = std::fs::write(&args_file, payload.to_string()).is_ok();
|
let wrote_args = std::fs::write(&args_file, payload.to_string()).is_ok();
|
||||||
|
|
||||||
if wrote_args {
|
if wrote_args {
|
||||||
if !helper_task_exists() {
|
if !helper_task_matches(exe) {
|
||||||
if let Err(e) = install_helper_task(exe) {
|
if let Err(e) = install_helper_task(exe) {
|
||||||
eprintln!("[OSTP] could not register the helper task ({e}); falling back to a direct elevated launch");
|
eprintln!("[OSTP] could not register the helper task ({e}); falling back to a direct elevated launch");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if helper_task_exists() {
|
if helper_task_matches(exe) {
|
||||||
let run = quiet_command("schtasks")
|
let run = quiet_command("schtasks")
|
||||||
.args(["/Run", "/TN", HELPER_TASK_NAME])
|
.args(["/Run", "/TN", HELPER_TASK_NAME])
|
||||||
.output();
|
.output();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "ostp-gui",
|
"productName": "ostp-gui",
|
||||||
"version": "0.4.3",
|
"version": "0.4.4",
|
||||||
"identifier": "com.ospab.ostp",
|
"identifier": "com.ospab.ostp",
|
||||||
"build": {
|
"build": {
|
||||||
"frontendDist": "../src"
|
"frontendDist": "../src"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue