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

@@ -358,10 +358,12 @@ impl PipelineExecutor {
.ok()
.and_then(|r| r.with_guessed_format().ok())
.and_then(|r| r.into_dimensions().ok());
// Apply regex find/replace on stem (matching the pixel path)
// Apply rename transformations on stem (matching the pixel path)
let working_stem = crate::operations::rename::apply_regex_replace(
stem, &rename.regex_find, &rename.regex_replace,
);
let working_stem = crate::operations::rename::apply_space_replacement(&working_stem, rename.replace_spaces);
let working_stem = crate::operations::rename::apply_special_chars(&working_stem, rename.special_chars);
let new_name = crate::operations::rename::apply_template_full(
template, &working_stem, ext,
rename.counter_start.saturating_add(index as u32),
@@ -512,10 +514,12 @@ impl PipelineExecutor {
let dims = Some((img.width(), img.height()));
let original_ext = source.path.extension()
.and_then(|e| e.to_str());
// Apply regex on the stem before template expansion
// Apply rename transformations on the stem before template expansion
let working_stem = crate::operations::rename::apply_regex_replace(
stem, &rename.regex_find, &rename.regex_replace,
);
let working_stem = crate::operations::rename::apply_space_replacement(&working_stem, rename.replace_spaces);
let working_stem = crate::operations::rename::apply_special_chars(&working_stem, rename.special_chars);
let new_name = crate::operations::rename::apply_template_full(
template,
&working_stem,
@@ -611,9 +615,9 @@ impl PipelineExecutor {
if !copy_metadata_from_source(&source.path, &output_path) {
eprintln!("Warning: failed to copy metadata to {}", output_path.display());
}
} else {
eprintln!("Warning: metadata cannot be preserved for {} format ({})", output_format.extension(), output_path.display());
}
// For non-JPEG/TIFF formats, metadata is lost during re-encoding
// and cannot be restored. This is a known limitation.
}
crate::operations::MetadataConfig::StripAll => {
// Already stripped by re-encoding - nothing to do

View File

@@ -63,7 +63,10 @@ impl Preset {
overwrite_behavior: crate::operations::OverwriteAction::default(),
preserve_directory_structure: false,
progressive_jpeg: false,
avif_speed: 6,
avif_speed: self.compress.as_ref().map(|c| match c {
crate::operations::CompressConfig::Preset(p) => p.avif_speed(),
_ => 6,
}).unwrap_or(6),
output_dpi: 72,
}
}