mirror of
https://git.proxmox.com/git/proxmox
synced 2025-05-03 18:30:11 +00:00
fix #3618: proxmox-async: zip: add conditional EFS flag to zip files
this flag marks the file names as 'UTF-8' encoded if they are valid UTF-8. By default, encoding of file names in zips are defined as code page 437, but we save the filenames as bytes (like in linux fs). For linux systems this would not be a problem since most tools simply use the filenames as bytes, but for the zip utility under windows it's important since NTFS uses UTF-16 for file names. For filenames that are valid UTF-8, they are decoded as UTF-8 everywhere correctly (Linux as UTF-8 bytes, Windows as correct UTF-16 sequence) and for other filenames with a high bit set, it depends on the OS/Software what exactly happens. Some cases below: * Windows + Built-in/7zip: decoded as CP437 * Debian + zip: Bytes taken as-is * Debian + 7z: interpreted as Windows1252, decoded as UTF-8 Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
This commit is contained in:
parent
1cc9b91c4f
commit
e4974b9891
@ -34,6 +34,9 @@ const VERSION_MADE_BY: u16 = 0x032d;
|
|||||||
const ZIP64_EOCD_RECORD: u32 = 0x06064B50;
|
const ZIP64_EOCD_RECORD: u32 = 0x06064B50;
|
||||||
const ZIP64_EOCD_LOCATOR: u32 = 0x07064B50;
|
const ZIP64_EOCD_LOCATOR: u32 = 0x07064B50;
|
||||||
|
|
||||||
|
const LFH_GENERAL_PURPOSE_FLAGS: u16 = 1 << 3; // we place crc32 in the data descriptor
|
||||||
|
const LFH_GPF_EFS_BIT: u16 = 1 << 11; // EFS, marks filename & comment as UTF-8
|
||||||
|
|
||||||
// bits for time:
|
// bits for time:
|
||||||
// 0-4: day of the month (1-31)
|
// 0-4: day of the month (1-31)
|
||||||
// 5-8: month: (1 = jan, etc.)
|
// 5-8: month: (1 = jan, etc.)
|
||||||
@ -200,6 +203,7 @@ pub struct ZipEntry {
|
|||||||
compressed_size: u64,
|
compressed_size: u64,
|
||||||
offset: u64,
|
offset: u64,
|
||||||
is_file: bool,
|
is_file: bool,
|
||||||
|
is_utf8_filename: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ZipEntry {
|
impl ZipEntry {
|
||||||
@ -220,8 +224,11 @@ impl ZipEntry {
|
|||||||
relpath.push(""); // adds trailing slash
|
relpath.push(""); // adds trailing slash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let filename: OsString = relpath.into();
|
||||||
|
let is_utf8_filename = filename.to_str().is_some();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
filename: relpath.into(),
|
filename,
|
||||||
crc32: 0,
|
crc32: 0,
|
||||||
mtime,
|
mtime,
|
||||||
mode,
|
mode,
|
||||||
@ -229,6 +236,15 @@ impl ZipEntry {
|
|||||||
compressed_size: 0,
|
compressed_size: 0,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
is_file,
|
is_file,
|
||||||
|
is_utf8_filename,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_general_purpose_flags(&self) -> u16 {
|
||||||
|
if self.is_utf8_filename {
|
||||||
|
LFH_GENERAL_PURPOSE_FLAGS | LFH_GPF_EFS_BIT
|
||||||
|
} else {
|
||||||
|
LFH_GENERAL_PURPOSE_FLAGS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,7 +265,7 @@ impl ZipEntry {
|
|||||||
LocalFileHeader {
|
LocalFileHeader {
|
||||||
signature: LOCAL_FH_SIG,
|
signature: LOCAL_FH_SIG,
|
||||||
version_needed: 0x2d,
|
version_needed: 0x2d,
|
||||||
flags: 1 << 3,
|
flags: self.get_general_purpose_flags(),
|
||||||
compression: 0x8,
|
compression: 0x8,
|
||||||
time,
|
time,
|
||||||
date,
|
date,
|
||||||
@ -332,7 +348,7 @@ impl ZipEntry {
|
|||||||
signature: CENTRAL_DIRECTORY_FH_SIG,
|
signature: CENTRAL_DIRECTORY_FH_SIG,
|
||||||
version_made_by: VERSION_MADE_BY,
|
version_made_by: VERSION_MADE_BY,
|
||||||
version_needed: VERSION_NEEDED,
|
version_needed: VERSION_NEEDED,
|
||||||
flags: 1 << 3,
|
flags: self.get_general_purpose_flags(),
|
||||||
compression: 0x8,
|
compression: 0x8,
|
||||||
time,
|
time,
|
||||||
date,
|
date,
|
||||||
|
Loading…
Reference in New Issue
Block a user