Fix 16 medium-severity bugs from audit

CLI: add UTC suffix to timestamps, validate image extensions on
single-file input, canonicalize watch paths for reliable matching,
derive counter_enabled from template presence, warn when undo count
exceeds available batches.

Core: apply space/special-char transforms in template rename path,
warn on metadata preservation for unsupported formats, derive AVIF
speed from compress preset quality level.

GTK: use buffer size for apples-to-apples compress preview comparison,
shorten approximate format labels, cache file sizes to avoid repeated
syscalls on checkbox toggle, add batch-update guard to prevent O(n^2)
in select/deselect all, use widget names for reliable progress/log
lookup, add unique suffix for duplicate download filenames.
This commit is contained in:
2026-03-07 23:02:57 +02:00
parent 9ef33fa90f
commit 9fcbe237bd
7 changed files with 136 additions and 50 deletions

View File

@@ -937,8 +937,6 @@ enum PreviewResult {
}
fn generate_preview(path: &std::path::Path, comp: PreviewCompression) -> PreviewResult {
let original_size = std::fs::metadata(path).map(|m| m.len()).unwrap_or(0);
let img = match image::open(path) {
Ok(img) => img,
Err(e) => return PreviewResult::Error(e.to_string()),
@@ -959,6 +957,10 @@ fn generate_preview(path: &std::path::Path, comp: PreviewCompression) -> Preview
return PreviewResult::Error("Failed to encode original".into());
}
// Use the preview buffer size for comparison (not on-disk size)
// so both original and compressed refer to the same downscaled image
let original_size = orig_buf.len() as u64;
// Encode compressed in the requested format
let mut comp_buf = Vec::new();
let format_label;
@@ -1008,9 +1010,9 @@ fn generate_preview(path: &std::path::Path, comp: PreviewCompression) -> Preview
}
}
PreviewCompression::WebP(quality) => {
// image 0.25 only has lossless WebP encoding, so approximate with
// JPEG at equivalent quality for the visual preview
format_label = format!("WebP Q{} (approx)", quality);
// image crate only has lossless WebP encoding, so approximate with
// JPEG at equivalent quality for the visual preview (size estimate only)
format_label = format!("~WebP Q{}", quality);
let cursor = std::io::Cursor::new(&mut comp_buf);
let encoder = image::codecs::jpeg::JpegEncoder::new_with_quality(cursor, quality);
let rgb = preview_img.to_rgb8();
@@ -1027,8 +1029,8 @@ fn generate_preview(path: &std::path::Path, comp: PreviewCompression) -> Preview
}
}
PreviewCompression::Avif(quality) => {
// AVIF encoding not available in image crate - approximate with JPEG
format_label = format!("AVIF Q{} (approx)", quality);
// AVIF encoding not available in image crate - approximate with JPEG (size estimate only)
format_label = format!("~AVIF Q{}", quality);
let cursor = std::io::Cursor::new(&mut comp_buf);
let encoder = image::codecs::jpeg::JpegEncoder::new_with_quality(cursor, quality);
let rgb = preview_img.to_rgb8();