实现内容: ✅ archive模块完整架构(10个文件,约900行) ✅ ArchiveProcessor trait统一接口 ✅ ProcessorRegistry插件式架构 ✅ FormatDetector格式自动检测 ✅ ArchiveConfig配置管理系统 ✅ Warning警告系统(RAR/XZ/7z争议格式) ✅ Zip Slip/Zip Bomb安全防护 ✅ 核心格式stub(ZIP/TAR/GZIP等9种) ✅ 可选格式stub(RAR/XZ/7z等3种) ✅ 测试框架基础 支持的格式: 核心格式(默认启用):ZIP, TAR, GZIP, ZSTD, BZIP2, LZ4, TAR.GZ, TAR.BZ2, TAR.ZST(9种) 可选格式(默认禁用):RAR(法律风险), XZ(外部依赖), 7z(库不稳定)(3种) 总计:12种压缩格式 安全特性: - Zip Slip防护(路径遍历攻击) - Zip Bomb防护(解压比率限制) - 文件大小限制 - 法律风险警告(RAR专利) 下一步:Phase 2 - 核心格式完整实现(ZIP/TAR/GZIP处理器)
152 lines
5.3 KiB
Rust
152 lines
5.3 KiB
Rust
// Archive Module - Universal Compression Format Support
|
|
// Supports 12 compression formats: 9 core + 3 optional
|
|
// Core: ZIP, TAR, GZIP, ZSTD, BZIP2, LZ4, TAR.GZ, TAR.BZ2, TAR.ZST
|
|
// Optional: RAR (legal risk), XZ (external dependency), 7z (unstable library)
|
|
|
|
pub mod config;
|
|
pub mod detector;
|
|
pub mod metadata;
|
|
pub mod processor;
|
|
pub mod warning;
|
|
|
|
pub mod processors {
|
|
pub mod core;
|
|
#[cfg(feature = "optional-formats")]
|
|
pub mod optional;
|
|
}
|
|
|
|
#[cfg(test)]
|
|
pub mod tests;
|
|
|
|
use anyhow::Result;
|
|
use std::collections::HashMap;
|
|
use std::path::Path;
|
|
|
|
use crate::archive::{ArchiveFormat, ArchiveProcessor, FormatDetector, ArchiveConfig};
|
|
|
|
/// Processor Registry - Plugin Architecture
|
|
pub struct ProcessorRegistry {
|
|
processors: HashMap<ArchiveFormat, Box<dyn ArchiveProcessor>>,
|
|
config: ArchiveConfig,
|
|
}
|
|
|
|
impl ProcessorRegistry {
|
|
/// Create new registry with config
|
|
pub fn new(config: ArchiveConfig) -> Self {
|
|
Self {
|
|
processors: HashMap::new(),
|
|
config,
|
|
}
|
|
}
|
|
|
|
/// Initialize all processors (based on config)
|
|
pub fn initialize(&mut self) -> Result<()> {
|
|
// Core formats (always registered)
|
|
self.register_core_processors()?;
|
|
|
|
// Optional formats (based on config)
|
|
self.register_optional_processors()?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Register core format processors (9 formats)
|
|
fn register_core_processors(&mut self) -> Result<()> {
|
|
use crate::archive::processors::core::*;
|
|
|
|
self.processors.insert(ArchiveFormat::Zip, Box::new(ZipProcessor::new()));
|
|
self.processors.insert(ArchiveFormat::Tar, Box::new(TarProcessor::new()));
|
|
self.processors.insert(ArchiveFormat::Gzip, Box::new(GzipProcessor::new()));
|
|
self.processors.insert(ArchiveFormat::Zstd, Box::new(ZstdProcessor::new()));
|
|
self.processors.insert(ArchiveFormat::Bzip2, Box::new(Bzip2Processor::new()));
|
|
self.processors.insert(ArchiveFormat::Lz4, Box::new(Lz4Processor::new()));
|
|
self.processors.insert(ArchiveFormat::TarGzip, Box::new(TarGzipProcessor::new()));
|
|
self.processors.insert(ArchiveFormat::TarBzip2, Box::new(TarBzip2Processor::new()));
|
|
self.processors.insert(ArchiveFormat::TarZstd, Box::new(TarZstdProcessor::new()));
|
|
|
|
info!("✅ Core formats registered: 9 formats");
|
|
Ok(())
|
|
}
|
|
|
|
/// Register optional format processors (3 formats, based on config)
|
|
fn register_optional_processors(&mut self) -> Result<()> {
|
|
#[cfg(feature = "optional-formats")]
|
|
{
|
|
use crate::archive::processors::optional::*;
|
|
|
|
// RAR format (legal risk)
|
|
if self.config.enable_rar {
|
|
crate::archive::warning::show_rar_legal_warning();
|
|
self.processors.insert(ArchiveFormat::Rar, Box::new(RarProcessor::new()));
|
|
warn!("⚠️ RAR format enabled (legal risk)");
|
|
}
|
|
|
|
// XZ format (external dependency)
|
|
if self.config.enable_xz {
|
|
if check_liblzma_available() {
|
|
self.processors.insert(ArchiveFormat::Xz, Box::new(XzProcessor::new()));
|
|
info!("✅ XZ format enabled");
|
|
} else {
|
|
crate::archive::warning::show_xz_dependency_warning();
|
|
warn!("⚠️ XZ format disabled (liblzma not found)");
|
|
}
|
|
}
|
|
|
|
// 7z format (unstable library)
|
|
if self.config.enable_7z {
|
|
crate::archive::warning::show_7z_stability_warning();
|
|
self.processors.insert(ArchiveFormat::SevenZ, Box::new(SevenZProcessor::new()));
|
|
warn!("⚠️ 7z format enabled (stability warning)");
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Get processor for detected format
|
|
pub fn get_processor(&self, path: &Path) -> Result<&dyn ArchiveProcessor> {
|
|
let detector = FormatDetector::new();
|
|
let format = detector.detect(path)?;
|
|
|
|
self.processors
|
|
.get(&format)
|
|
.map(|p| p.as_ref())
|
|
.ok_or_else(|| anyhow::anyhow!("Format {} not supported or not enabled", format))
|
|
}
|
|
|
|
/// List all enabled formats
|
|
pub fn enabled_formats(&self) -> Vec<ArchiveFormat> {
|
|
self.processors.keys().cloned().collect()
|
|
}
|
|
}
|
|
|
|
/// Check if liblzma library is available
|
|
#[cfg(feature = "optional-formats")]
|
|
fn check_liblzma_available() -> bool {
|
|
// Try to load xz2 library
|
|
// Simplified check: try to create XzProcessor
|
|
true // Simplified for now, actual implementation needs better detection
|
|
}
|
|
|
|
#[cfg(not(feature = "optional-formats"))]
|
|
fn check_liblzma_available() -> bool {
|
|
false
|
|
}
|
|
|
|
/// Initialize archive system with config
|
|
pub fn init_archive_system(config_path: Option<&str>) -> Result<ProcessorRegistry> {
|
|
let config = if let Some(path) = config_path {
|
|
ArchiveConfig::load(path)?
|
|
} else {
|
|
ArchiveConfig::default()
|
|
};
|
|
|
|
// Show startup warnings for optional formats
|
|
crate::archive::warning::show_startup_warnings(&config);
|
|
|
|
let mut registry = ProcessorRegistry::new(config);
|
|
registry.initialize()?;
|
|
|
|
info!("Archive system initialized with {} formats", registry.enabled_formats().len());
|
|
Ok(registry)
|
|
} |