Archive Module Phase 1: 核心框架搭建完成 ⭐⭐⭐⭐⭐
实现内容: ✅ 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处理器)
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
// 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)
|
||||
}
|
||||
Reference in New Issue
Block a user