zip/extra_fields/
zipinfo_utf8.rs

1use crate::result::{invalid, ZipResult};
2use crate::unstable::LittleEndianReadExt;
3use core::mem::size_of;
4use std::io::Read;
5
6/// Info-ZIP Unicode Path Extra Field (0x7075) or Unicode Comment Extra Field (0x6375), as
7/// specified in APPNOTE 4.6.8 and 4.6.9
8#[derive(Clone, Debug)]
9pub struct UnicodeExtraField {
10    crc32: u32,
11    content: Box<[u8]>,
12}
13
14impl UnicodeExtraField {
15    /// Verifies the checksum and returns the content.
16    pub fn unwrap_valid(self, ascii_field: &[u8]) -> ZipResult<Box<[u8]>> {
17        let mut crc32 = crc32fast::Hasher::new();
18        crc32.update(ascii_field);
19        let actual_crc32 = crc32.finalize();
20        if self.crc32 != actual_crc32 {
21            return Err(invalid!("CRC32 checksum failed on Unicode extra field"));
22        }
23        Ok(self.content)
24    }
25}
26
27impl UnicodeExtraField {
28    pub(crate) fn try_from_reader<R: Read>(reader: &mut R, len: u16) -> ZipResult<Self> {
29        // Read and discard version byte
30        reader.read_exact(&mut [0u8])?;
31
32        let crc32 = reader.read_u32_le()?;
33        let content_len = (len as usize)
34            .checked_sub(size_of::<u8>() + size_of::<u32>())
35            .ok_or(invalid!("Unicode extra field is too small"))?;
36        let mut content = vec![0u8; content_len].into_boxed_slice();
37        reader.read_exact(&mut content)?;
38        Ok(Self { crc32, content })
39    }
40}