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}