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
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:
parent
7d47e67bfc
commit
0e619753f1
@ -99,6 +99,75 @@ finally:
|
||||
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)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
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"
|
||||
))?;
|
||||
|
||||
install_linux_capture_filter()?;
|
||||
let ppd_path = build_fieldlens_ppd(target_printer)?;
|
||||
let filter_dir = cups_filter_dir()?;
|
||||
let filter_path = filter_dir.join("fieldlens-capture");
|
||||
|
||||
let production_args = vec![
|
||||
"-p".to_string(),
|
||||
"FieldLens-Print".to_string(),
|
||||
"-E".to_string(),
|
||||
"-v".to_string(),
|
||||
target.port.clone(),
|
||||
"-P".to_string(),
|
||||
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 temp_filter = std::env::temp_dir().join(format!(
|
||||
"fieldlens-capture-{}.py",
|
||||
uuid::Uuid::new_v4()
|
||||
));
|
||||
let temp_helper = std::env::temp_dir().join(format!(
|
||||
"fieldlens-cups-repair-{}.py",
|
||||
uuid::Uuid::new_v4()
|
||||
));
|
||||
|
||||
let test_args = vec![
|
||||
"-p".to_string(),
|
||||
TEST_VIRTUAL_PRINTER_QUEUE.to_string(),
|
||||
"-E".to_string(),
|
||||
"-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?;
|
||||
fs::write(&temp_filter, FIELDLENS_CUPS_FILTER)
|
||||
.context("write FieldLens CUPS capture filter")?;
|
||||
fs::write(&temp_helper, FIELDLENS_CUPS_REPAIR_HELPER)
|
||||
.context("write FieldLens CUPS repair helper")?;
|
||||
|
||||
// Explicitly repair both CUPS state flags because Chromium disables Print
|
||||
// when either is stale.
|
||||
for queue in ["FieldLens-Print", TEST_VIRTUAL_PRINTER_QUEUE] {
|
||||
run_cups_repair_command("cupsenable", &[queue])?;
|
||||
run_cups_repair_command("cupsaccept", &[queue])?;
|
||||
let status = Command::new("pkexec")
|
||||
.arg("python3")
|
||||
.arg(&temp_helper)
|
||||
.arg(target_printer)
|
||||
.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(())
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user