From 9e8747872b515d49bb7da22876065dcd3005c1bf Mon Sep 17 00:00:00 2001 From: Sam Rijs Date: Tue, 6 Nov 2018 23:13:20 +1100 Subject: [PATCH] Defer parsing of local file header --- src/read.rs | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/src/read.rs b/src/read.rs index de614eb0..246e1604 100644 --- a/src/read.rs +++ b/src/read.rs @@ -282,15 +282,28 @@ impl ZipArchive pub fn by_index<'a>(&'a mut self, file_number: usize) -> ZipResult> { if file_number >= self.files.len() { return Err(ZipError::FileNotFound); } - let ref data = self.files[file_number]; - let pos = data.data_start; + let ref mut data = self.files[file_number]; if data.encrypted { return unsupported_zip_error("Encrypted files are not supported") } - self.reader.seek(io::SeekFrom::Start(pos))?; + // Parse local header + self.reader.seek(io::SeekFrom::Start(data.header_start))?; + let signature = self.reader.read_u32::()?; + if signature != spec::LOCAL_FILE_HEADER_SIGNATURE + { + return Err(ZipError::InvalidArchive("Invalid local file header")) + } + + self.reader.seek(io::SeekFrom::Current(22))?; + let file_name_length = self.reader.read_u16::()? as u64; + let extra_field_length = self.reader.read_u16::()? as u64; + let magic_and_header = 4 + 22 + 2 + 2; + data.data_start = data.header_start + magic_and_header + file_name_length + extra_field_length; + + self.reader.seek(io::SeekFrom::Start(data.data_start))?; let limit_reader = (self.reader.by_ref() as &mut Read).take(data.compressed_size); Ok(ZipFile { reader: make_reader(data.compression_method, data.crc32, limit_reader)?, data: Cow::Borrowed(data) }) @@ -374,26 +387,6 @@ fn central_header_to_zip_file(reader: &mut R, archive_offset: // Account for shifted zip offsets. result.header_start += archive_offset; - // Remember end of central header - let return_position = reader.seek(io::SeekFrom::Current(0))?; - - // Parse local header - reader.seek(io::SeekFrom::Start(result.header_start))?; - let signature = reader.read_u32::()?; - if signature != spec::LOCAL_FILE_HEADER_SIGNATURE - { - return Err(ZipError::InvalidArchive("Invalid local file header")) - } - - reader.seek(io::SeekFrom::Current(22))?; - let file_name_length = reader.read_u16::()? as u64; - let extra_field_length = reader.read_u16::()? as u64; - let magic_and_header = 4 + 22 + 2 + 2; - result.data_start = result.header_start + magic_and_header + file_name_length + extra_field_length; - - // Go back after the central header - reader.seek(io::SeekFrom::Start(return_position))?; - Ok(result) }