@@ -9,8 +9,7 @@ use crate::extra_fields::{ExtendedTimestamp, ExtraField, Ntfs};
99use crate :: read:: zip_archive:: { Shared , SharedBuilder } ;
1010use crate :: result:: invalid;
1111use crate :: result:: { ZipError , ZipResult } ;
12- use crate :: spec:: { self , DataAndPosition ,
13- FixedSizeBlock , Magic , Zip32CentralDirectoryEnd } ;
12+ use crate :: spec:: { self , CentralDirectoryEndInfo , DataAndPosition , FixedSizeBlock , Magic , Pod } ;
1413use crate :: types:: {
1514 AesMode , AesVendorVersion , DateTime , System , ZipCentralEntryBlock , ZipDataDescriptor ,
1615 ZipFileData , ZipLocalEntryBlock , ZipLocalEntryBlockAndFields ,
@@ -1909,6 +1908,34 @@ impl<R: Read> Drop for ZipFile<'_, R> {
19091908 }
19101909}
19111910
1911+ /// Read ZipFile structures from a non-seekable reader.
1912+ ///
1913+ /// This is an alternative method to read a zip file. If possible, use the ZipArchive functions
1914+ /// as some information will be missing when reading this manner.
1915+ ///
1916+ /// Reads a file header from the start of the stream. Will return `Ok(Some(..))` if a file is
1917+ /// present at the start of the stream. Returns `Ok(None)` if the start of the central directory
1918+ /// is encountered. No more files should be read after this.
1919+ ///
1920+ /// The Drop implementation of ZipFile ensures that the reader will be correctly positioned after
1921+ /// the structure is done.
1922+ ///
1923+ /// Missing fields are:
1924+ /// * `comment`: set to an empty string
1925+ /// * `data_start`: set to 0
1926+ /// * `external_attributes`: `unix_mode()`: will return None
1927+ pub fn read_zipfile_from_stream < R : Read > ( reader : & mut R ) -> ZipResult < Option < ZipFile < ' _ , R > > > {
1928+ let block = read_local_fileblock ( reader) ?;
1929+ let block = match block {
1930+ Some ( block) => block,
1931+ None => return Ok ( None ) ,
1932+ } ;
1933+
1934+ // we can't look for a data descriptor since we can't seek back
1935+ // TODO: provide a method that buffers the read data and allows seeking back
1936+ read_zipfile_from_fileblock ( block, reader, None )
1937+ }
1938+
19121939/// A filter that determines whether an entry should be ignored when searching
19131940/// for the root directory of a Zip archive.
19141941///
@@ -1950,11 +1977,11 @@ pub fn root_dir_common_filter(path: &Path) -> bool {
19501977
19511978 if path. components ( ) . count ( ) == 1
19521979 && path. file_name ( ) . is_some_and ( |file_name| {
1953- COMMON_FILTER_ROOT_FILES
1954- . iter ( )
1955- . map ( OsStr :: new)
1956- . any ( |cmp| cmp == file_name)
1957- } )
1980+ COMMON_FILTER_ROOT_FILES
1981+ . iter ( )
1982+ . map ( OsStr :: new)
1983+ . any ( |cmp| cmp == file_name)
1984+ } )
19581985 {
19591986 return false ;
19601987 }
@@ -1994,12 +2021,12 @@ fn read_local_fileblock<R: Read>(reader: &mut R) -> ZipResult<Option<ZipLocalEnt
19942021 } ) )
19952022}
19962023
1997- fn read_zipfile_from_fileblock < ' a , R : Read > (
2024+ fn read_zipfile_from_fileblock < R : Read > (
19982025 block : ZipLocalEntryBlockAndFields ,
1999- reader : & ' a mut R ,
2026+ reader : & mut R ,
20002027 data_descriptor : Option < ZipDataDescriptor > ,
2001- ) -> ZipResult < Option < ZipFile < ' _ > > > {
2002- let mut result = ZipFileData :: from_local_block ( block, data_descriptor) ?;
2028+ ) -> ZipResult < Option < ZipFile < R > > > {
2029+ let mut result = ZipFileData :: from_local_block ( block, data_descriptor, reader ) ?;
20032030
20042031 match crate :: read:: parse_extra_field ( & mut result) {
20052032 Ok ( ..) | Err ( ZipError :: Io ( ..) ) => { }
@@ -2029,37 +2056,6 @@ fn read_zipfile_from_fileblock<'a, R: Read>(
20292056 } ) )
20302057}
20312058
2032- /// Read ZipFile structures from a non-seekable reader.
2033- ///
2034- /// This is an alternative method to read a zip file. If possible, use the ZipArchive functions
2035- /// as some information will be missing when reading this manner.
2036- ///
2037- /// Reads a file header from the start of the stream. Will return `Ok(Some(..))` if a file is
2038- /// present at the start of the stream. Returns `Ok(None)` if the start of the central directory
2039- /// is encountered. No more files should be read after this.
2040- ///
2041- /// The Drop implementation of ZipFile ensures that the reader will be correctly positioned after
2042- /// the structure is done.
2043- ///
2044- /// This method will not find a ZipFile entry if the zip file uses data descriptors.
2045- /// In that case you could use [read_zipfile_from_seekable_stream]
2046- ///
2047- /// Missing fields are:
2048- /// * `comment`: set to an empty string
2049- /// * `data_start`: set to 0
2050- /// * `external_attributes`: `unix_mode()`: will return None
2051- pub fn read_zipfile_from_stream < ' a , R : Read > ( reader : & ' a mut R ) -> ZipResult < Option < ZipFile < ' _ > > > {
2052- let block = read_local_fileblock ( reader) ?;
2053- let block = match block {
2054- Some ( block) => block,
2055- None => return Ok ( None ) ,
2056- } ;
2057-
2058- // we can't look for a data descriptor since we can't seek back
2059- // TODO: provide a method that buffers the read data and allows seeking back
2060- read_zipfile_from_fileblock ( block, reader, None )
2061- }
2062-
20632059/// Read ZipFile structures from a seekable reader.
20642060///
20652061/// This is an alternative method to read a zip file. If possible, use the ZipArchive functions
@@ -2095,7 +2091,7 @@ pub fn read_zipfile_from_stream<'a, R: Read>(reader: &'a mut R) -> ZipResult<Opt
20952091/// * `external_attributes`: `unix_mode()`: will return None
20962092pub fn read_zipfile_from_seekablestream < S : Read + Seek > (
20972093 reader : & mut S ,
2098- ) -> ZipResult < Option < ZipFile > > {
2094+ ) -> ZipResult < Option < ZipFile < S > > > {
20992095 let local_entry_block = read_local_fileblock ( reader) ?;
21002096 let local_entry_block = match local_entry_block {
21012097 Some ( local_entry_block) => local_entry_block,
@@ -2134,15 +2130,14 @@ pub fn read_zipfile_from_seekablestream<S: Read + Seek>(
21342130 reader. seek ( SeekFrom :: Current ( -4 ) ) ?; // go back to the start of the data descriptor
21352131 read_count_total -= 4 ;
21362132
2137- let mut data_descriptor_block = [ 0u8 ; mem:: size_of :: < ZipDataDescriptor > ( ) ] ;
2138- reader. read_exact ( & mut data_descriptor_block) ?;
2139- let data_descriptor_block: Box < [ u8 ] > = data_descriptor_block. into ( ) ;
2133+ let mut data_descriptor = ZipDataDescriptor :: zeroed ( ) ;
2134+ reader. read_exact ( data_descriptor. as_bytes_mut ( ) ) ?;
21402135 // seek back to data end
21412136 reader. seek ( SeekFrom :: Current (
21422137 -( mem:: size_of :: < ZipDataDescriptor > ( ) as i64 ) ,
21432138 ) ) ?;
21442139
2145- let data_descriptor = ZipDataDescriptor :: interpret ( & data_descriptor_block ) ? ;
2140+ let data_descriptor = ZipDataDescriptor :: from_le ( data_descriptor ) ;
21462141
21472142 // check if the data descriptor is indeed valid for the read data
21482143 if data_descriptor. compressed_size == read_count_total as u32 {
0 commit comments