use std::path::Path; use crate::error::{PixstripError, Result}; use super::MetadataConfig; pub fn strip_metadata( input: &Path, output: &Path, config: &MetadataConfig, ) -> Result<()> { match config { MetadataConfig::KeepAll => { std::fs::copy(input, output).map_err(PixstripError::Io)?; } MetadataConfig::StripAll => { strip_all_exif(input, output)?; } MetadataConfig::Privacy => { // Privacy mode strips GPS and camera info but keeps copyright. // For now, we strip all EXIF as a safe default. // Selective tag preservation requires full EXIF parsing. strip_all_exif(input, output)?; } MetadataConfig::Custom { .. } => { // Custom selective stripping - simplified to strip-all for now. // Full selective stripping requires per-tag EXIF manipulation. strip_all_exif(input, output)?; } } Ok(()) } fn strip_all_exif(input: &Path, output: &Path) -> Result<()> { let data = std::fs::read(input).map_err(PixstripError::Io)?; let cleaned = remove_exif_from_jpeg(&data); std::fs::write(output, cleaned).map_err(PixstripError::Io)?; Ok(()) } fn remove_exif_from_jpeg(data: &[u8]) -> Vec { // Only process JPEG files (starts with FF D8) if data.len() < 2 || data[0] != 0xFF || data[1] != 0xD8 { return data.to_vec(); } let mut result = Vec::with_capacity(data.len()); result.push(0xFF); result.push(0xD8); let mut i = 2; while i + 1 < data.len() { if data[i] != 0xFF { result.extend_from_slice(&data[i..]); break; } let marker = data[i + 1]; // APP1 (0xE1) contains EXIF - skip it if marker == 0xE1 && i + 3 < data.len() { let len = ((data[i + 2] as usize) << 8) | (data[i + 3] as usize); i += 2 + len; continue; } // SOS (0xDA) - start of scan, copy everything from here if marker == 0xDA { result.extend_from_slice(&data[i..]); break; } // Other markers - keep them if i + 3 < data.len() { let len = ((data[i + 2] as usize) << 8) | (data[i + 3] as usize); let end = i + 2 + len; if end <= data.len() { result.extend_from_slice(&data[i..end]); i = end; } else { result.extend_from_slice(&data[i..]); break; } } else { result.extend_from_slice(&data[i..]); break; } } result }