explore files
This commit is contained in:
parent
0794aac016
commit
0d305fbe62
5 changed files with 189 additions and 47 deletions
|
|
@ -1,14 +1,14 @@
|
|||
use std::io::{SeekFrom, Write};
|
||||
|
||||
use crate::extra_fields::{ExtraField, GenericExtraField, Zip64ExtraField};
|
||||
use crate::{cp437, Encoding, Signature};
|
||||
use crate::{cp437, general_purpose_flags, Encoding, Signature};
|
||||
use androscalpel_serializer::{ReadSeek, Result, Serializable};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct LocalFileHeader {
|
||||
// signature: Signature(0x04034b50)
|
||||
pub version_needed_to_extract: u16,
|
||||
pub general_purpose_flag: u16,
|
||||
pub general_purpose_flags: u16,
|
||||
pub compression_method: u16,
|
||||
pub last_mod_file_time: u16,
|
||||
pub last_mod_file_data: u16,
|
||||
|
|
@ -21,13 +21,14 @@ pub struct LocalFileHeader {
|
|||
pub extra_field: Vec<ExtraField>,
|
||||
/// Remaining bytes in the extra_fields that could not be parsed as ExtraField
|
||||
pub malformed_extra_field: Vec<u8>,
|
||||
pub decryption_header: Option<DecryptionHeader>,
|
||||
}
|
||||
|
||||
impl Serializable for LocalFileHeader {
|
||||
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
|
||||
Self::SIGNATURE.serialize(output)?;
|
||||
self.version_needed_to_extract.serialize(output)?;
|
||||
self.general_purpose_flag.serialize(output)?;
|
||||
self.general_purpose_flags.serialize(output)?;
|
||||
self.compression_method.serialize(output)?;
|
||||
self.last_mod_file_time.serialize(output)?;
|
||||
self.last_mod_file_data.serialize(output)?;
|
||||
|
|
@ -45,15 +46,17 @@ impl Serializable for LocalFileHeader {
|
|||
for c in &self.malformed_extra_field {
|
||||
c.serialize(output)?;
|
||||
}
|
||||
if let Some(header) = &self.decryption_header {
|
||||
header.serialize(output)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
|
||||
let signature = Signature::deserialize(input)?;
|
||||
assert_eq!(signature, Self::SIGNATURE); // TODO
|
||||
let version_made_by = u16::deserialize(input)?;
|
||||
let version_needed_to_extract = u16::deserialize(input)?;
|
||||
let general_purpose_flag = u16::deserialize(input)?;
|
||||
let general_purpose_flags = u16::deserialize(input)?;
|
||||
let compression_method = u16::deserialize(input)?;
|
||||
let last_mod_file_time = u16::deserialize(input)?;
|
||||
let last_mod_file_data = u16::deserialize(input)?;
|
||||
|
|
@ -62,18 +65,13 @@ impl Serializable for LocalFileHeader {
|
|||
let uncompressed_size = u32::deserialize(input)?;
|
||||
let file_name_length = u16::deserialize(input)?;
|
||||
let extra_field_length = u16::deserialize(input)?;
|
||||
let file_comment_length = u16::deserialize(input)?;
|
||||
let disk_number_start = u16::deserialize(input)?;
|
||||
let internal_file_attributes = u16::deserialize(input)?;
|
||||
let external_file_attributes = u32::deserialize(input)?;
|
||||
let offset_local_header = u32::deserialize(input)?;
|
||||
let mut file_name = vec![];
|
||||
for _ in 0..file_name_length {
|
||||
file_name.push(u8::deserialize(input)?);
|
||||
}
|
||||
let mut header = Self {
|
||||
version_needed_to_extract,
|
||||
general_purpose_flag,
|
||||
general_purpose_flags,
|
||||
compression_method,
|
||||
last_mod_file_time,
|
||||
last_mod_file_data,
|
||||
|
|
@ -83,6 +81,7 @@ impl Serializable for LocalFileHeader {
|
|||
file_name,
|
||||
extra_field: vec![],
|
||||
malformed_extra_field: vec![],
|
||||
decryption_header: None,
|
||||
};
|
||||
//let end_of_extra_field = input.stream_position().unwrap() + extra_field_length as u64;
|
||||
let extra_field_off = input.stream_position().unwrap();
|
||||
|
|
@ -123,8 +122,8 @@ impl Serializable for LocalFileHeader {
|
|||
{
|
||||
let original_size = uncompressed_size == u32::MAX;
|
||||
let compressed_size = compressed_size == u32::MAX;
|
||||
let offset_header = offset_local_header == u32::MAX;
|
||||
let disk_number = disk_number_start == u16::MAX;
|
||||
let offset_header = false;
|
||||
let disk_number = false;
|
||||
let zip64_filed = Zip64ExtraField::from_generic(
|
||||
&GenericExtraField {
|
||||
id: Zip64ExtraField::ID,
|
||||
|
|
@ -139,6 +138,12 @@ impl Serializable for LocalFileHeader {
|
|||
*field = ExtraField::Zip64(zip64_filed);
|
||||
}
|
||||
}
|
||||
if (header.general_purpose_flags & general_purpose_flags::MASK_ENCRYPTED != 0)
|
||||
&& (header.general_purpose_flags & general_purpose_flags::MASK_STRONG_ENCRYPTION != 0)
|
||||
{
|
||||
header.decryption_header = Some(DecryptionHeader::deserialize(input)?);
|
||||
}
|
||||
|
||||
Ok(header)
|
||||
}
|
||||
|
||||
|
|
@ -147,6 +152,11 @@ impl Serializable for LocalFileHeader {
|
|||
+ self.file_name.len()
|
||||
+ self.extra_field.iter().map(|f| f.size()).sum::<usize>()
|
||||
+ self.malformed_extra_field.len()
|
||||
+ self
|
||||
.decryption_header
|
||||
.as_ref()
|
||||
.map(|h| h.size())
|
||||
.unwrap_or(0)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -157,7 +167,7 @@ impl LocalFileHeader {
|
|||
const MASK_UTF8_FILENAME: u16 = 1 << 11;
|
||||
|
||||
pub fn get_name_encoding(&self) -> Encoding {
|
||||
if self.general_purpose_flag & Self::MASK_UTF8_FILENAME != 0 {
|
||||
if self.general_purpose_flags & Self::MASK_UTF8_FILENAME != 0 {
|
||||
Encoding::UTF8
|
||||
} else {
|
||||
Encoding::CP437
|
||||
|
|
@ -205,3 +215,47 @@ impl LocalFileHeader {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct DecryptionHeader {
|
||||
// pub ivsize: u16,
|
||||
pub iv_data: Vec<u8>,
|
||||
// pub remaining_size: u32,
|
||||
// TODO: parse, not needed for now
|
||||
pub other_data: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Serializable for DecryptionHeader {
|
||||
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
|
||||
(self.iv_data.len() as u16).serialize(output)?;
|
||||
for c in &self.iv_data {
|
||||
c.serialize(output)?;
|
||||
}
|
||||
(self.other_data.len() as u32).serialize(output)?;
|
||||
for c in &self.other_data {
|
||||
c.serialize(output)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
|
||||
let iv_size = u16::deserialize(input)?;
|
||||
let mut iv_data = vec![];
|
||||
for _ in 0..iv_size {
|
||||
iv_data.push(u8::deserialize(input)?);
|
||||
}
|
||||
let remaining_size = u32::deserialize(input)?;
|
||||
let mut other_data = vec![];
|
||||
for _ in 0..remaining_size {
|
||||
other_data.push(u8::deserialize(input)?);
|
||||
}
|
||||
Ok(Self {
|
||||
iv_data,
|
||||
other_data,
|
||||
})
|
||||
}
|
||||
|
||||
fn size(&self) -> usize {
|
||||
2 + self.iv_data.len() + 4 + self.other_data.len()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue