zip_core/raw/
mod.rs

1//! `zip-core::raw` contains 1:1 memory format of zip headers for use in your
2//! projects  e.g. if you want to build your own zip crate.
3//!
4//! Note: for concenience, all structs with variable size are split into a fixed
5//! part and the variable part. The fixed part is prepended with `Fixed`. This
6//! should make parsing easier
7//!
8//!
9//! ### Rage List of things about <https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT>
10//! - all fields unless noted are unsigned and little endian (there are no
11//!   notions), however we should set one to -1 in 4.4.1.4, how?!?!
12//! - optional signature that are not standart but are recomended.
13//! - noone explains what zip64 does, what it tries to do, etc.
14//! - measurements, sometimes its offset, sometimes total size, sometimes
15//!   remaining size, and sometimes, size from this byte onwards
16//!
17//! #### Naming Rage
18//! During reading the document I almost had a seizure regarding to naming.
19//! Nevertheless I decided against renaming fields, as this is what the author
20//! PKWARE decided on, and probably the whole industry has adopted to and i dont
21//! want to create xkcd:927 However, if in future revisions some names are
22//! adopted I would be more than happy. Here are some of the incompatibilities
23//!
24//! - of all fields and structures, sometimes sturct, sometimes record, often
25//!   nothing
26//! - sometimes central dir, sometimes central directory
27//! - Zip64 end of central directory locator vs Zip64 end of central directory
28//!   locator record
29//! - the central directory is sometimes a single central directory header and
30//!   sometimes a central directory structure
31//! - sometimes its a length sometimes a size
32extern crate alloc;
33use alloc::vec::Vec;
34
35#[cfg(feature = "parse")] pub mod parse;
36
37/// part of [`LocalFileHeader`] which has a fixed size
38///
39/// [`LocalFileHeader`]: LocalFileHeader
40#[derive(Debug, Clone, PartialEq)]
41pub struct LocalFileHeaderFixed {
42    pub local_file_header_signature: u32,
43    pub version_needed_to_extract: u16,
44    pub general_purpose_bit_flag: u16,
45    pub compression_method: u16,
46    pub last_mod_file_time: u16,
47    pub last_mod_file_date: u16,
48    pub crc_32: u32,
49    pub compressed_size: u32,
50    pub uncompressed_size: u32,
51    pub file_name_length: u16,
52    pub extra_field_length: u16,
53}
54
55/// Local File Header
56///
57/// The local file header is prepended before each file.
58/// The bytes after it are usually the file or an Encryption Header.
59/// is is linked by an [`CentralDirectoryHeader`]
60///
61/// see [4.3.7](https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT)
62///
63/// [`CentralDirectoryHeader`]: CentralDirectoryHeader
64#[derive(Debug, Clone, PartialEq)]
65pub struct LocalFileHeader {
66    pub fixed:       LocalFileHeaderFixed,
67    pub file_name:   Vec<u8>,
68    pub extra_field: Vec<u8>,
69}
70
71/// Data descriptor
72///
73/// the data descriptior is prepended to the file data.
74/// It might be used sometimes, in this case the corresponding fields in
75/// [`LocalFileHeader`] are zero.
76///
77/// Note: There exists a zip64 variant of this descriptor:
78/// [`DataDescriptorZip64`] Note: the DataDescriptor should contain a signature,
79/// see the struct [`DataDescriptorSignature`]. Its not standart but recomended.
80/// When parsing you are on your own if the first 4 bytes a the signature or
81/// just a random crc32 according to the documentation
82/// see [`DataDescriptorZip64Signature`] for Zip64 with Signature
83///
84/// see [4.3.9](https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT)
85///
86/// [`LocalFileHeader`]: LocalFileHeaderFixed
87/// [`DataDescriptorZip64`]: DataDescriptorZip64
88/// [`DataDescriptorSignature`]: DataDescriptorSignature
89/// [`DataDescriptorZip64Signature`]: DataDescriptorZip64Signature
90#[derive(Debug, Clone, PartialEq)]
91pub struct DataDescriptor {
92    pub crc_32: u32,
93    pub compressed_size: u32,
94    pub uncompressed_size: u32,
95}
96
97/// Data descriptor with a signature see [`DataDescriptor`]
98///
99/// [`DataDescriptor`]: DataDescriptor
100#[derive(Debug, Clone, PartialEq)]
101pub struct DataDescriptorSignature {
102    pub signature: u32,
103    pub crc_32: u32,
104    pub compressed_size: u32,
105    pub uncompressed_size: u32,
106}
107
108/// Data descriptor for Zip64, sizes are 8 bytes instead of 4, see
109/// [`DataDescriptor`]
110///
111/// [`DataDescriptor`]: DataDescriptor
112#[derive(Debug, Clone, PartialEq)]
113pub struct DataDescriptorZip64 {
114    pub crc_32: u32,
115    pub compressed_size: u64,
116    pub uncompressed_size: u64,
117}
118
119/// Data descriptor for Zip64, sizes are 8 bytes instead of 4 and with a
120/// signature, see [`DataDescriptor`]
121///
122/// [`DataDescriptor`]: DataDescriptor
123#[derive(Debug, Clone, PartialEq)]
124pub struct DataDescriptorZip64Signature {
125    pub signature: u32,
126    pub crc_32: u32,
127    pub compressed_size: u64,
128    pub uncompressed_size: u64,
129}
130
131/// part of [`ArchiveExtraDataRecord`] which has a fixed size
132///
133/// [`ArchiveExtraDataRecord`]: ArchiveExtraDataRecord
134#[derive(Debug, Clone, PartialEq)]
135pub struct ArchiveExtraDataRecordFixed {
136    pub archive_extra_data_signature: u32,
137    pub extra_field_length: u64,
138}
139
140/// Archive Extra Data Record
141///
142/// May be used to support the Central Directory Encryption Feature
143///
144/// see [4.3.11](https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT)
145#[derive(Debug, Clone, PartialEq)]
146pub struct ArchiveExtraDataRecord {
147    pub fixed: ArchiveExtraDataRecordFixed,
148    pub extra_field_data: Vec<u8>,
149}
150
151/// part of [`CentralDirectoryHeader`] which has a fixed size
152///
153/// [`CentralDirectoryHeader`]: CentralDirectoryHeader
154#[derive(Debug, Clone, PartialEq)]
155pub struct CentralDirectoryHeaderFixed {
156    pub central_file_header_signature: u32,
157    pub version_made_by: u16,
158    pub version_needed_to_extract: u16,
159    pub general_purpose_bit_flag: u16,
160    pub compression_method: u16,
161    pub last_mod_file_time: u16,
162    pub last_mod_file_date: u16,
163    pub crc_32: u32,
164    pub compressed_size: u32,
165    pub uncompressed_size: u32,
166    pub file_name_length: u16,
167    pub extra_field_length: u16,
168    pub file_comment_length: u16,
169    pub disk_number_start: u16,
170    pub internal_file_attributes: u16,
171    pub external_file_attributes: u32,
172    pub relative_offset_of_local_header: u32,
173}
174
175/// Central Directory Header
176///
177/// The Central Directory Structure contains of multiple Central Directory
178/// Headers and a Digital Signature. Note: the documentation is confusing about
179/// this, the Digital Signature is left out in `4.3.6` and Archive Decryption
180/// Header and [`ArchiveExtraDataRecord`] seem to be not part of it, though they
181/// have a strong dependency.
182///
183/// Each Central Directory Header links to exactly one [`LocalFileHeader`]
184///
185/// see [4.3.12](https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT)
186///
187/// [`ArchiveExtraDataRecord`]: ArchiveExtraDataRecord
188/// [`LocalFileHeader`]: LocalFileHeader
189#[derive(Debug, Clone, PartialEq)]
190pub struct CentralDirectoryHeader {
191    pub fixed:        CentralDirectoryHeaderFixed,
192    pub file_name:    Vec<u8>,
193    pub extra_field:  Vec<u8>,
194    pub file_comment: Vec<u8>,
195}
196
197/// part of [`DigitalSignature`] which has a fixed size
198///
199/// [`DigitalSignature`]: DigitalSignature
200#[derive(Debug, Clone, PartialEq)]
201pub struct DigitalSignatureFixed {
202    pub header_signature: u32,
203    pub size_of_data:     u16,
204}
205
206/// part of [`LocalFileHeader`] which has a fixed size
207///
208/// [`LocalFileHeader`]: LocalFileHeader
209#[derive(Debug, Clone, PartialEq)]
210pub struct DigitalSignature {
211    pub fixed: DigitalSignatureFixed,
212    pub signature_data: Vec<u8>,
213}
214
215/// Zip64 end of central directory record
216///
217/// see [4.3.14](https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT)
218#[derive(Debug, Clone, PartialEq)]
219pub struct Zip64EndOfCentralDirectoryFixed {
220    pub zip64_end_of_central_dir_signature: u32,
221    pub size_of_zip64_end_of_central_directory_record: u64,
222    pub version_made_by: u16,
223    pub version_needed_to_extract: u16,
224    pub number_of_this_disk: u32,
225    pub number_of_the_disk_with_the_start_of_the_central_directory: u32,
226    pub total_number_of_entries_in_the_central_directory_on_this_disk: u64,
227    pub total_number_of_entries_in_the_central_directory: u64,
228    pub size_of_the_central_directory: u64,
229    pub offset_of_start_of_central_directory_with_respect_to_the_starting_disk_number: u64,
230}
231
232/// part of [`Zip64EndOfCentralDirectory`] which has a fixed size
233///
234/// [`Zip64EndOfCentralDirectory`]: Zip64EndOfCentralDirectory
235#[derive(Debug, Clone, PartialEq)]
236pub struct Zip64EndOfCentralDirectory {
237    pub fixed: Zip64EndOfCentralDirectoryFixed,
238    pub zip64_extensible_data_sector: Vec<u8>,
239}
240
241///  Zip64 end of central directory locator
242///
243/// see [4.3.14](https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT)
244#[derive(Debug, Clone, PartialEq)]
245pub struct Zip64EndOfCentralDirectoryLocator {
246    pub zip64_end_of_central_dir_locator_signature: u32,
247    pub number_of_the_disk_with_the_start_of_the_central_directory: u32,
248    pub relative_offset_of_the_zip64_end_of_central_directory_record: u64,
249    pub number_of_this_disk: u32,
250}
251
252/// part of [`EndOfCentralDirectory`] which has a fixed size
253///
254/// [`EndOfCentralDirectory`]: EndOfCentralDirectory
255#[derive(Debug, Clone, PartialEq)]
256pub struct EndOfCentralDirectoryFixed {
257    pub end_of_central_dir_signature: u32,
258    pub number_of_this_disk: u16,
259    pub number_of_the_disk_with_the_start_of_the_central_directory: u16,
260    pub total_number_of_entries_in_the_central_directory_on_this_disk: u16,
261    pub total_number_of_entries_in_the_central_directory: u16,
262    pub size_of_the_central_directory: u32,
263    pub offset_of_start_of_central_directory_with_respect_to_the_starting_disk_number: u32,
264    pub zip_file_comment_length: u16,
265}
266
267/// End of central directory record
268///
269/// see [4.3.16](https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT)
270#[derive(Debug, Clone, PartialEq)]
271pub struct EndOfCentralDirectory {
272    pub fixed: EndOfCentralDirectoryFixed,
273    pub zip_file_comment: Vec<u8>,
274}
275
276/// part of [`ExtensibleData`] which has a fixed size
277///
278/// [`ExtensibleData`]: ExtensibleData
279#[derive(Debug, Clone, PartialEq)]
280pub struct ExtensibleDataFixed {
281    pub header_id: u16,
282    pub data_size: u16,
283}
284
285/// Extensible data fields
286///
287/// often called `extra field` in above Records, they are used to store
288/// additional information, like better file times or zip64 data.
289/// You prob want to parse the `extra_data` of a record with those in case your
290/// program is interested in Extensible Data. According to APPNOTE.TXT, programs
291/// that don't understand certain headers should just ignore them.
292///
293/// see [4.5.1](https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT)
294#[derive(Debug, Clone, PartialEq)]
295pub struct ExtensibleData {
296    pub fixed: ExtensibleDataFixed,
297    pub data:  Vec<u8>,
298}
299
300impl LocalFileHeaderFixed {
301    pub const LOCAL_FILE_HEADER_SIGNATURE: u32 = 0x04034b50;
302    pub const SIZE_IN_BYTES: usize = 30;
303}
304
305impl DataDescriptor {
306    /// Note: At time of writing this is an optional, de-facto-standart
307    /// signature
308    pub const SIGNATURE: u32 = 0x08074b50;
309    pub const SIZE_IN_BYTES: usize = 12;
310}
311
312impl DataDescriptorSignature {
313    pub const SIZE_IN_BYTES: usize = 16;
314}
315
316impl DataDescriptorZip64 {
317    pub const SIZE_IN_BYTES: usize = 20;
318}
319
320impl DataDescriptorZip64Signature {
321    pub const SIZE_IN_BYTES: usize = 24;
322}
323
324impl ArchiveExtraDataRecordFixed {
325    pub const SIZE_IN_BYTES: usize = 12;
326}
327
328impl ArchiveExtraDataRecordFixed {
329    pub const ARCHIVE_EXTRA_DATE_SIGNATURE: u32 = 0x08064b50;
330}
331
332impl CentralDirectoryHeaderFixed {
333    pub const CENTRAL_FILE_HEADER_SIGNATURE: u32 = 0x02014b50;
334    pub const SIZE_IN_BYTES: usize = 46;
335}
336
337impl DigitalSignatureFixed {
338    pub const HEADER_SIGNATURE: u32 = 0x05054b50;
339    pub const SIZE_IN_BYTES: usize = 6;
340}
341
342impl Zip64EndOfCentralDirectoryFixed {
343    pub const SIZE_IN_BYTES: usize = 56;
344    pub const ZIP64_END_OF_CENTRAL_DIR_SIGNATURE: u32 = 0x06064b50;
345}
346
347impl Zip64EndOfCentralDirectoryLocator {
348    pub const SIZE_IN_BYTES: usize = 20;
349    pub const ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE: u32 = 0x07064b50;
350}
351
352impl EndOfCentralDirectoryFixed {
353    pub const END_OF_CENTRAL_DIR_SIGNATURE: u32 = 0x06054b50;
354    pub const SIZE_IN_BYTES: usize = 22;
355}
356
357impl ExtensibleDataFixed {
358    pub const SIZE_IN_BYTES: usize = 4;
359}