put extra field in another file

This commit is contained in:
Jean-Marie Mineau 2024-01-15 15:27:08 +01:00
parent fafbdb6537
commit bea2b9ffc0
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
3 changed files with 142 additions and 137 deletions

View file

@ -0,0 +1,139 @@
use std::io::{Cursor, Write};
use androscalpel_serializer::{ReadSeek, Result, Serializable};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ExtraField {
Zip64(Zip64ExtraField),
Generic(GenericExtraField),
}
impl ExtraField {
fn to_generic(&self) -> Result<GenericExtraField> {
match self {
Self::Zip64(field) => field.to_generic_field(),
Self::Generic(field) => Ok(field.clone()),
}
}
}
impl Serializable for ExtraField {
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
self.to_generic()?.serialize(output)
}
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
Ok(Self::Generic(GenericExtraField::deserialize(input)?))
/*
match field.id {
Zip64ExtraField::ID => Ok(Self::Zip64(Zip64ExtraField::from_generic(&field)?)),
_ => Ok(Self::Generic(field)),
}
*/
}
fn size(&self) -> usize {
self.to_generic().unwrap().size()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Zip64ExtraField {
pub original_size: Option<u64>,
pub compressed_size: Option<u64>,
pub offset_header: Option<u64>,
pub disk_number: Option<u32>,
}
impl Zip64ExtraField {
pub const ID: u16 = 0x0001;
fn to_generic_field(&self) -> Result<GenericExtraField> {
let mut data = Cursor::new(Vec::<u8>::new());
if let Some(original_size) = self.original_size {
original_size.serialize(&mut data)?;
}
if let Some(compressed_size) = self.compressed_size {
compressed_size.serialize(&mut data)?;
}
if let Some(offset_header) = self.offset_header {
offset_header.serialize(&mut data)?;
}
if let Some(disk_number) = self.disk_number {
disk_number.serialize(&mut data)?;
}
Ok(GenericExtraField {
id: Self::ID,
data: data.into_inner(),
})
}
pub fn from_generic(
field: &GenericExtraField,
original_size: bool,
compressed_size: bool,
offset_header: bool,
disk_number: bool,
) -> Result<Self> {
assert_eq!(field.id, Self::ID);
let mut data = Cursor::new(&field.data);
let original_size = if original_size {
Some(u64::deserialize(&mut data)?)
} else {
None
};
let compressed_size = if compressed_size {
Some(u64::deserialize(&mut data)?)
} else {
None
};
let offset_header = if offset_header {
Some(u64::deserialize(&mut data)?)
} else {
None
};
let disk_number = if disk_number {
Some(u32::deserialize(&mut data)?)
} else {
None
};
Ok(Self {
original_size,
compressed_size,
offset_header,
disk_number,
})
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GenericExtraField {
pub id: u16,
pub data: Vec<u8>,
}
impl Serializable for GenericExtraField {
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
self.id.serialize(output)?;
(self.data.len() as u16).serialize(output)?;
for c in &self.data {
c.serialize(output)?;
}
Ok(())
}
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
let id = u16::deserialize(input)?;
let data_size = u16::deserialize(input)?;
let mut data = vec![];
for _ in 0..data_size {
data.push(u8::deserialize(input)?);
}
Ok(Self { id, data })
}
fn size(&self) -> usize {
4 + self.data.len()
}
}

View file

@ -1,5 +1,6 @@
use std::io::{Cursor, SeekFrom, Write}; use std::io::{SeekFrom, Write};
use crate::extra_fields::{ExtraField, GenericExtraField, Zip64ExtraField};
use crate::{cp437, Signature}; use crate::{cp437, Signature};
use androscalpel_serializer::{ReadSeek, Result, Serializable}; use androscalpel_serializer::{ReadSeek, Result, Serializable};
@ -8,142 +9,6 @@ pub enum Encoding {
UTF8, UTF8,
} }
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ExtraField {
Zip64(Zip64ExtraField),
Generic(GenericExtraField),
}
impl ExtraField {
fn to_generic(&self) -> Result<GenericExtraField> {
match self {
Self::Zip64(field) => field.to_generic_field(),
Self::Generic(field) => Ok(field.clone()),
}
}
}
impl Serializable for ExtraField {
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
self.to_generic()?.serialize(output)
}
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
Ok(Self::Generic(GenericExtraField::deserialize(input)?))
/*
match field.id {
Zip64ExtraField::ID => Ok(Self::Zip64(Zip64ExtraField::from_generic(&field)?)),
_ => Ok(Self::Generic(field)),
}
*/
}
fn size(&self) -> usize {
self.to_generic().unwrap().size()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Zip64ExtraField {
original_size: Option<u64>,
compressed_size: Option<u64>,
offset_header: Option<u64>,
disk_number: Option<u32>,
}
impl Zip64ExtraField {
const ID: u16 = 0x0001;
fn to_generic_field(&self) -> Result<GenericExtraField> {
let mut data = Cursor::new(Vec::<u8>::new());
if let Some(original_size) = self.original_size {
original_size.serialize(&mut data)?;
}
if let Some(compressed_size) = self.compressed_size {
compressed_size.serialize(&mut data)?;
}
if let Some(offset_header) = self.offset_header {
offset_header.serialize(&mut data)?;
}
if let Some(disk_number) = self.disk_number {
disk_number.serialize(&mut data)?;
}
Ok(GenericExtraField {
id: Self::ID,
data: data.into_inner(),
})
}
fn from_generic(
field: &GenericExtraField,
original_size: bool,
compressed_size: bool,
offset_header: bool,
disk_number: bool,
) -> Result<Self> {
assert_eq!(field.id, Self::ID);
let mut data = Cursor::new(&field.data);
let original_size = if original_size {
Some(u64::deserialize(&mut data)?)
} else {
None
};
let compressed_size = if compressed_size {
Some(u64::deserialize(&mut data)?)
} else {
None
};
let offset_header = if offset_header {
Some(u64::deserialize(&mut data)?)
} else {
None
};
let disk_number = if disk_number {
Some(u32::deserialize(&mut data)?)
} else {
None
};
Ok(Self {
original_size,
compressed_size,
offset_header,
disk_number,
})
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GenericExtraField {
pub id: u16,
pub data: Vec<u8>,
}
impl Serializable for GenericExtraField {
fn serialize(&self, output: &mut dyn Write) -> Result<()> {
self.id.serialize(output)?;
(self.data.len() as u16).serialize(output)?;
for c in &self.data {
c.serialize(output)?;
}
Ok(())
}
fn deserialize(input: &mut dyn ReadSeek) -> Result<Self> {
let id = u16::deserialize(input)?;
let data_size = u16::deserialize(input)?;
let mut data = vec![];
for _ in 0..data_size {
data.push(u8::deserialize(input)?);
}
Ok(Self { id, data })
}
fn size(&self) -> usize {
4 + self.data.len()
}
}
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct FileHeader { pub struct FileHeader {
// signature: Signature(0x02014b50) // signature: Signature(0x02014b50)

View file

@ -5,6 +5,7 @@ use androscalpel_serializer::Serializable;
pub mod apk_signing_block; pub mod apk_signing_block;
mod cp437; mod cp437;
pub mod end_of_central_directory; pub mod end_of_central_directory;
pub mod extra_fields;
pub mod file_header; pub mod file_header;
use apk_signing_block::*; use apk_signing_block::*;