diff --git a/apk_frauder/src/data_descriptor.rs b/apk_frauder/src/data_descriptor.rs new file mode 100644 index 0000000..2daa834 --- /dev/null +++ b/apk_frauder/src/data_descriptor.rs @@ -0,0 +1,117 @@ +use crate::Signature; +use androscalpel_serializer::{ReadSeek, Result, Serializable}; +use std::io::{SeekFrom, Write}; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum DataDescriptor { + Zip32(DataDescriptor32), + Zip64(DataDescriptor64), +} + +/// DataDescriptor for 32bit zip format. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct DataDescriptor32 { + // signature: Option + pub crc_32: u32, + pub compressed_size: u32, + pub uncompressed_size: u32, + /// For reproducibility. This should be true when writting a zip, but can be false when + /// reading one. If we want to stick to the original, we need to keep this information. + pub use_signature: bool, +} + +/// DataDescriptor for 64bit zip format. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct DataDescriptor64 { + // signature: Option + pub crc_32: u32, + pub compressed_size: u64, + pub uncompressed_size: u64, + /// For reproducibility. This should be true when writting a zip, but can be false when + /// reading one. If we want to stick to the original, we need to keep this information. + pub use_signature: bool, +} + +impl DataDescriptor32 { + const SIGNATURE: Signature = Signature(0x02014b50); +} + +impl Serializable for DataDescriptor32 { + fn serialize(&self, output: &mut dyn Write) -> Result<()> { + if self.use_signature { + Self::SIGNATURE.serialize(output)?; + } + self.crc_32.serialize(output)?; + self.compressed_size.serialize(output)?; + self.uncompressed_size.serialize(output) + } + + fn deserialize(input: &mut dyn ReadSeek) -> Result { + let pos = input.stream_position().unwrap(); //TODO + let signature = Signature::deserialize(input)?; + let use_signature = if signature != Self::SIGNATURE { + input.seek(SeekFrom::Start(pos)).unwrap(); //TODO + false + } else { + true + }; + let crc_32 = u32::deserialize(input)?; + let compressed_size = u32::deserialize(input)?; + let uncompressed_size = u32::deserialize(input)?; + Ok(Self { + crc_32, + compressed_size, + uncompressed_size, + use_signature, + }) + } + fn size(&self) -> usize { + 12 + if self.use_signature { + Self::SIGNATURE.size() + } else { + 0 + } + } +} + +impl DataDescriptor64 { + const SIGNATURE: Signature = Signature(0x02014b50); +} + +impl Serializable for DataDescriptor64 { + fn serialize(&self, output: &mut dyn Write) -> Result<()> { + if self.use_signature { + Self::SIGNATURE.serialize(output)?; + } + self.crc_32.serialize(output)?; + self.compressed_size.serialize(output)?; + self.uncompressed_size.serialize(output) + } + + fn deserialize(input: &mut dyn ReadSeek) -> Result { + let pos = input.stream_position().unwrap(); //TODO + let signature = Signature::deserialize(input)?; + let use_signature = if signature != Self::SIGNATURE { + input.seek(SeekFrom::Start(pos)).unwrap(); //TODO + false + } else { + true + }; + let crc_32 = u32::deserialize(input)?; + let compressed_size = u64::deserialize(input)?; + let uncompressed_size = u64::deserialize(input)?; + Ok(Self { + crc_32, + compressed_size, + uncompressed_size, + use_signature, + }) + } + fn size(&self) -> usize { + 20 + if self.use_signature { + Self::SIGNATURE.size() + } else { + 0 + } + } +}