97 lines
3 KiB
Rust
97 lines
3 KiB
Rust
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;
|
|
}
|
|
}
|
|
}
|