Files
markbase/markbase-core/src/archive/mod.rs
Warren 55db79cb8d 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处理器)
2026-06-10 17:21:42 +08:00

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)
}