Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/extra_fields/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,9 @@ pub struct CustomExtraField {
/// If true, this field will be included in the central directory entry but not the local file header.
pub(crate) central_only: bool,
/// Header ID of the extra field
pub(crate) header_id: u16,
pub header_id: u16,
/// Data of the extra field
data: Box<[u8]>,
pub data: Box<[u8]>,
}

impl CustomExtraField {
Expand Down
70 changes: 70 additions & 0 deletions tests/zip_extra_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,73 @@ fn test_extra_field_too_long() {
}
}
}

#[test]
fn test_alignment_extra_field_local_only() {
use std::io::{Cursor, Write};
use zip::CompressionMethod;
use zip::ZipArchive;
use zip::write::{SimpleFileOptions, ZipWriter};

let mut writer = ZipWriter::new(Cursor::new(Vec::new()));
let options = SimpleFileOptions::default()
.compression_method(CompressionMethod::Stored)
.with_alignment(16);
writer.start_file("test.txt", options).unwrap();
writer.write_all(b"hello world").unwrap();
let zip_bytes = writer.finish().unwrap().into_inner();

// Verify 0xa11e alignment tag is present in the local header bytes
let tag = (0xa11e_u16).to_le_bytes();
assert_eq!(
zip_bytes.windows(2).filter(|w| *w == tag).count(),
1,
"Local header must contain alignment extra field tag 0xa11e"
);

// Central directory should not contain DataStreamAlignment
let mut archive = ZipArchive::new(Cursor::new(&zip_bytes)).unwrap();
let file = archive.by_name("test.txt").unwrap();
let has_alignment_central = file.extra_data_fields().any(|ef| {
matches!(
ef,
zip::extra_fields::ExtraField::DataStreamAlignment { .. }
)
});
assert!(
!has_alignment_central,
"Central directory header must NOT contain DataStreamAlignment"
);
}

#[test]
fn test_custom_central_only_extra_field() {
use std::io::{Cursor, Write};
use zip::CompressionMethod;
use zip::ZipArchive;
use zip::extra_fields::ExtraField;
use zip::write::{FileOptions, ZipWriter};

let mut writer = ZipWriter::new(Cursor::new(Vec::new()));
let mut options = FileOptions::default().compression_method(CompressionMethod::Stored);
options
.add_extra_field(0x1234, vec![0xAB, 0xCD], true)
.unwrap(); // central_only = true

writer.start_file("central_only.txt", options).unwrap();
writer.write_all(b"content").unwrap();
let bytes = writer.finish().unwrap().into_inner();

let mut archive = ZipArchive::new(Cursor::new(bytes)).unwrap();
let file = archive.by_name("central_only.txt").unwrap();

// Central directory should have this field
let has_custom_central = file.extra_data_fields().any(|ef| match ef {
ExtraField::Custom(cef) => cef.header_id == 0x1234 && *cef.data == [0xAB, 0xCD],
_ => false,
});
assert!(
has_custom_central,
"Central directory header must contain central_only custom field"
);
}