fix(linux): repair FieldLens CUPS queues with one privilege prompt
Some checks failed
Desktop Release / Bootstrap updater signing key (push) Has been cancelled
Desktop Release / Windows x64 NSIS (push) Has been cancelled
Desktop Release / Linux x64 DEB + AppImage (push) Has been cancelled
Desktop Release / Publish public desktop release (push) Has been cancelled

This commit is contained in:
Admin 2026-09-24 09:16:15 +00:00
parent 7d47e67bfc
commit 0e619753f1

View File

@ -99,6 +99,75 @@ finally:
pass pass
"#; "#;
#[cfg(target_os = "linux")]
const FIELDLENS_CUPS_REPAIR_HELPER: &str = r#"#!/usr/bin/python3
import os
import subprocess
import sys
import tempfile
target_printer = sys.argv[1]
target_port = sys.argv[2]
temp_filter = sys.argv[3]
filter_path = sys.argv[4]
source_ppd = os.path.join("/etc/cups/ppd", f"{target_printer}.ppd")
spool_dir = "/var/cache/cups/fieldlens-print"
with open(source_ppd, "r", encoding="utf-8", errors="replace") as source:
original = source.read()
cleaned = "\n".join(
line for line in original.splitlines()
if "fieldlens-capture" not in line
) + "\n"
prefilter = (
"*% FieldLens original-document capture before cups-filters universal conversion\n"
"*cupsPreFilter: \"application/vnd.universal-input 0 fieldlens-capture\"\n"
)
index = cleaned.rfind("*% End")
if index >= 0:
cleaned = cleaned[:index] + prefilter + cleaned[index:]
else:
cleaned += prefilter
fd, ppd_path = tempfile.mkstemp(prefix="fieldlens-", suffix=".ppd")
os.close(fd)
try:
with open(ppd_path, "w", encoding="utf-8") as target:
target.write(cleaned)
subprocess.run(["install", "-m", "0755", temp_filter, filter_path], check=True)
subprocess.run(["install", "-d", "-m", "0777", spool_dir], check=True)
subprocess.run([
"lpadmin", "-p", "FieldLens-Print", "-E",
"-v", target_port,
"-P", ppd_path,
"-D", "FieldLens Print",
], check=True)
subprocess.run([
"lpadmin", "-p", "FieldLens-Test-Capture", "-E",
"-v", "socket://127.0.0.1:9101",
"-P", ppd_path,
"-D", "FieldLens Test Capture",
], check=True)
for queue in ("FieldLens-Print", "FieldLens-Test-Capture"):
subprocess.run(["cupsenable", queue], check=True)
subprocess.run(["cupsaccept", queue], check=True)
finally:
try:
os.unlink(ppd_path)
except OSError:
pass
"#;
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct SystemPrinter { pub struct SystemPrinter {
@ -603,51 +672,42 @@ fn install_linux_virtual_printer(target_printer: &str) -> Result<()> {
"selected printer '{target_printer}' is not installed or available in CUPS" "selected printer '{target_printer}' is not installed or available in CUPS"
))?; ))?;
install_linux_capture_filter()?; let filter_dir = cups_filter_dir()?;
let ppd_path = build_fieldlens_ppd(target_printer)?; let filter_path = filter_dir.join("fieldlens-capture");
let production_args = vec![ let temp_filter = std::env::temp_dir().join(format!(
"-p".to_string(), "fieldlens-capture-{}.py",
"FieldLens-Print".to_string(), uuid::Uuid::new_v4()
"-E".to_string(), ));
"-v".to_string(), let temp_helper = std::env::temp_dir().join(format!(
target.port.clone(), "fieldlens-cups-repair-{}.py",
"-P".to_string(), uuid::Uuid::new_v4()
ppd_path.to_string_lossy().into_owned(), ));
"-D".to_string(),
VIRTUAL_PRINTER_NAME.to_string(),
];
run_linux_admin(
"lpadmin",
&production_args,
"configure FieldLens production CUPS printer",
)?;
let test_args = vec![ fs::write(&temp_filter, FIELDLENS_CUPS_FILTER)
"-p".to_string(), .context("write FieldLens CUPS capture filter")?;
TEST_VIRTUAL_PRINTER_QUEUE.to_string(), fs::write(&temp_helper, FIELDLENS_CUPS_REPAIR_HELPER)
"-E".to_string(), .context("write FieldLens CUPS repair helper")?;
"-v".to_string(),
TEST_CAPTURE_DEVICE_URI.to_string(),
"-P".to_string(),
ppd_path.to_string_lossy().into_owned(),
"-D".to_string(),
TEST_VIRTUAL_PRINTER_NAME.to_string(),
];
let test_result = run_linux_admin(
"lpadmin",
&test_args,
"configure FieldLens test-capture CUPS printer",
);
let _ = fs::remove_file(&ppd_path);
test_result?;
// Explicitly repair both CUPS state flags because Chromium disables Print let status = Command::new("pkexec")
// when either is stale. .arg("python3")
for queue in ["FieldLens-Print", TEST_VIRTUAL_PRINTER_QUEUE] { .arg(&temp_helper)
run_cups_repair_command("cupsenable", &[queue])?; .arg(target_printer)
run_cups_repair_command("cupsaccept", &[queue])?; .arg(&target.port)
.arg(&temp_filter)
.arg(&filter_path)
.status()
.context("run elevated FieldLens CUPS repair")?;
let _ = fs::remove_file(&temp_filter);
let _ = fs::remove_file(&temp_helper);
if !status.success() {
return Err(anyhow!(
"FieldLens printer repair failed; administrator approval may be required"
));
} }
Ok(()) Ok(())
} }