use androscalpel_serializer::Serializable; pub mod apk_signing_block; pub mod compression; mod cp437; pub mod end_of_central_directory; pub mod extra_fields; pub mod file_header; pub mod local_file_header; pub mod zip_reader; pub mod zip_writer; use extra_fields::{ExtraField, Zip64ExtraField}; use file_header::FileHeader; use local_file_header::LocalFileHeader; pub use zip_reader::ZipFileReader; pub use zip_writer::ZipFileWriter; #[derive(Debug, Clone, PartialEq, Eq, Serializable, Default)] pub struct Signature(pub u32); pub enum Encoding { CP437, UTF8, } pub mod general_purpose_flags { pub const MASK_ENCRYPTED: u16 = 1 << 0; pub const MASK_COMPRESS_OPTION_1: u16 = 1 << 1; pub const MASK_COMPRESS_OPTION_2: u16 = 1 << 2; pub const MASK_USE_DATA_DESCRIPTOR: u16 = 1 << 3; pub const MASK_STRONG_ENCRYPTION: u16 = 1 << 6; pub const MASK_UTF8_FILENAME: u16 = 1 << 11; pub const MASK_ENCRYPTED_CENTRAL_DIR: u16 = 1 << 13; } #[derive(Debug, Clone, PartialEq, Eq)] pub struct FileInfo { pub local_header: LocalFileHeader, pub header: FileHeader, } // TODO: support data descriptor (MASK_USE_DATA_DESCRIPTOR) impl FileInfo { pub fn get_name(&self) -> String { self.header.get_name() } pub fn get_offset_local_header(&self) -> u64 { self.header.get_offset_local_header() } pub fn get_compressed_size(&self) -> u64 { self.header.get_compressed_size() } pub fn get_file_offset(&self) -> u64 { self.get_offset_local_header() + self.local_header.size() as u64 } pub fn set_offset_local_header(&mut self, new_offset: u64) { let use_z64 = new_offset > u32::MAX as u64; for extra in &mut self.local_header.extra_field { if let ExtraField::Zip64(extra) = extra { if use_z64 { extra.offset_header = Some(new_offset); } else { extra.offset_header = None; } } } let mut z64found = false; for extra in &mut self.header.extra_field { if let ExtraField::Zip64(extra) = extra { if use_z64 { extra.offset_header = Some(new_offset); } else { extra.offset_header = None; } z64found = true; } } if use_z64 && !z64found { self.header .extra_field .push(ExtraField::Zip64(Zip64ExtraField { original_size: Some(self.header.uncompressed_size as u64), compressed_size: Some(self.header.compressed_size as u64), offset_header: Some(new_offset), disk_number: None, })); self.header.uncompressed_size = u32::MAX; self.header.compressed_size = u32::MAX; } if use_z64 { self.header.offset_local_header = u32::MAX; } else { self.header.offset_local_header = new_offset as u32; } } }