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
|
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(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user