Compare commits

..

No commits in common. "cf14a4243c81bf230da9867fa936f659f88c9d15" and "bc61b4781797a3c3907362802f64348ccc61679a" have entirely different histories.

9 changed files with 27 additions and 87 deletions

View File

@ -1,6 +1,6 @@
{ {
"target_version": "0.4.4", "target_version": "0.4.3",
"branch": "master", "branch": "master",
"alpha_iteration": 0, "alpha_iteration": 0,
"beta_iteration": 0 "beta_iteration": 4
} }

12
Cargo.lock generated
View File

@ -1386,7 +1386,7 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]] [[package]]
name = "ostp" name = "ostp"
version = "0.4.4" version = "0.4.3"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"base64", "base64",
@ -1409,7 +1409,7 @@ dependencies = [
[[package]] [[package]]
name = "ostp-client" name = "ostp-client"
version = "0.4.4" version = "0.4.3"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"base64", "base64",
@ -1440,7 +1440,7 @@ dependencies = [
[[package]] [[package]]
name = "ostp-core" name = "ostp-core"
version = "0.4.4" version = "0.4.3"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytes", "bytes",
@ -1474,7 +1474,7 @@ dependencies = [
[[package]] [[package]]
name = "ostp-server" name = "ostp-server"
version = "0.4.4" version = "0.4.3"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"axum", "axum",
@ -1507,7 +1507,7 @@ dependencies = [
[[package]] [[package]]
name = "ostp-tun" name = "ostp-tun"
version = "0.4.4" version = "0.4.3"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"libc", "libc",
@ -1519,7 +1519,7 @@ dependencies = [
[[package]] [[package]]
name = "ostp-tun-helper" name = "ostp-tun-helper"
version = "0.4.4" version = "0.4.3"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"chrono", "chrono",

View File

@ -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.4" version = "0.4.3"
[workspace.dependencies] [workspace.dependencies]
anyhow = "1.0" anyhow = "1.0"

View File

@ -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.4+31 version: 0.4.3+30
environment: environment:
sdk: ^3.11.4 sdk: ^3.11.4

View File

@ -1,7 +1,7 @@
{ {
"name": "ostp-gui", "name": "ostp-gui",
"private": true, "private": true,
"version": "0.4.4", "version": "0.4.3",
"type": "module", "type": "module",
"scripts": { "scripts": {
"tauri": "tauri", "tauri": "tauri",

View File

@ -2665,7 +2665,7 @@ dependencies = [
[[package]] [[package]]
name = "ostp-client" name = "ostp-client"
version = "0.4.4" version = "0.4.3"
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.4" version = "0.4.3"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytes", "bytes",
@ -2713,7 +2713,7 @@ dependencies = [
[[package]] [[package]]
name = "ostp-gui" name = "ostp-gui"
version = "0.4.4" version = "0.4.3"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"json_comments", "json_comments",
@ -2733,7 +2733,7 @@ dependencies = [
[[package]] [[package]]
name = "ostp-tun" name = "ostp-tun"
version = "0.4.4" version = "0.4.3"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"libc", "libc",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ostp-gui" name = "ostp-gui"
version = "0.4.4" version = "0.4.3"
description = "OSTP desktop GUI" description = "OSTP desktop GUI"
authors = ["ospab"] authors = ["ospab"]
edition = "2021" edition = "2021"

View File

@ -849,74 +849,14 @@ fn xml_escape(s: &str) -> String {
.replace('\'', "'") .replace('\'', "'")
} }
/// Reverse of [`xml_escape`]. `&` must be undone last or `<` would /// Whether the elevated-launch Scheduled Task already exists.
/// come back as `<`.
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
fn xml_unescape(s: &str) -> String { fn helper_task_exists() -> bool {
s.replace("&quot;", "\"") quiet_command("schtasks")
.replace("&apos;", "'") .args(["/Query", "/TN", HELPER_TASK_NAME])
.replace("&lt;", "<")
.replace("&gt;", ">")
.replace("&amp;", "&")
}
/// 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()
.ok()?; .map(|o| o.status.success())
if !out.status.success() { .unwrap_or(false)
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
@ -1026,10 +966,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_matches(exe) { if helper_task_exists() {
Ok(()) Ok(())
} else { } else {
anyhow::bail!("schtasks reported success but the task does not point at {}", exe.display()) anyhow::bail!("schtasks reported success but the task is not present")
} }
} }
@ -1054,12 +994,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_matches(exe) { if !helper_task_exists() {
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_matches(exe) { if helper_task_exists() {
let run = quiet_command("schtasks") let run = quiet_command("schtasks")
.args(["/Run", "/TN", HELPER_TASK_NAME]) .args(["/Run", "/TN", HELPER_TASK_NAME])
.output(); .output();

View File

@ -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.4", "version": "0.4.3",
"identifier": "com.ospab.ostp", "identifier": "com.ospab.ostp",
"build": { "build": {
"frontendDist": "../src" "frontendDist": "../src"