aboutsummaryrefslogtreecommitdiff
path: root/src/zip/file/read.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/zip/file/read.rs')
-rw-r--r--src/zip/file/read.rs88
1 files changed, 40 insertions, 48 deletions
diff --git a/src/zip/file/read.rs b/src/zip/file/read.rs
index aa665c3..c26b304 100644
--- a/src/zip/file/read.rs
+++ b/src/zip/file/read.rs
@@ -17,11 +17,12 @@ enum Encryption<Io: Read> {
17} 17}
18 18
19impl<Io: Read> Encryption<Io> { 19impl<Io: Read> Encryption<Io> {
20 pub fn new(io: Io, method: EncryptionMethod, password: Option<&str>) -> ZipResult<Self> { 20 pub fn new(io: Io, info: &ZipFileInfo, password: Option<&[u8]>) -> ZipResult<Self> {
21 Ok(match method { 21 Ok(match info.encryption_method {
22 EncryptionMethod::None => Self::None(io), 22 EncryptionMethod::None => Self::None(io),
23 EncryptionMethod::Weak => Self::Weak(WeakDecoder::new( 23 EncryptionMethod::Weak(check) => Self::Weak(WeakDecoder::new(
24 io, 24 io,
25 check,
25 password.ok_or(ZipError::PasswordIsNotSpecified)?, 26 password.ok_or(ZipError::PasswordIsNotSpecified)?,
26 )?), 27 )?),
27 EncryptionMethod::Unsupported => { 28 EncryptionMethod::Unsupported => {
@@ -61,12 +62,29 @@ enum Compression<Io: Read> {
61} 62}
62 63
63impl<Io: Read + Seek> Compression<Io> { 64impl<Io: Read + Seek> Compression<Io> {
64 pub fn new(io: Io, method: CompressionMethod) -> ZipResult<Self> { 65 pub fn new(mut io: Io, info: &ZipFileInfo) -> ZipResult<Self> {
65 Ok(match method { 66 Ok(match info.compression_method {
66 CompressionMethod::Store => Self::Store(io), 67 CompressionMethod::Store => Self::Store(io),
67 CompressionMethod::Deflate => Self::Deflate(DeflateDecoder::new(io)), 68 CompressionMethod::Deflate => Self::Deflate(DeflateDecoder::new(io)),
68 CompressionMethod::BZip2 => Self::BZip2(BzDecoder::new(io)), 69 CompressionMethod::BZip2 => Self::BZip2(BzDecoder::new(io)),
69 CompressionMethod::Lzma => panic!(), 70 CompressionMethod::Lzma => {
71 let buf = io.read_arr::<9>()?;
72 Compression::Xz(XzDecoder::new_stream(
73 io,
74 Stream::new_raw_decoder(
75 Filters::new().lzma1(
76 LzmaOptions::new()
77 .literal_context_bits((buf[4] % 9) as u32)
78 .literal_position_bits((buf[4] / 9 % 5) as u32)
79 .position_bits((buf[4] / 45) as u32)
80 .dict_size(
81 u32::from_le_bytes(buf[5..9].try_into().unwrap()).max(4096),
82 ),
83 ),
84 )
85 .unwrap(),
86 ))
87 }
70 CompressionMethod::Zstd => Self::Zstd(ZstdDecoder::new(io)?), 88 CompressionMethod::Zstd => Self::Zstd(ZstdDecoder::new(io)?),
71 CompressionMethod::Xz => Self::Xz(XzDecoder::new(io)), 89 CompressionMethod::Xz => Self::Xz(XzDecoder::new(io)),
72 CompressionMethod::Unsupported(id) => { 90 CompressionMethod::Unsupported(id) => {
@@ -108,14 +126,14 @@ pub struct ZipFileReader<'d, Io: Read> {
108impl<'d, Io: Read> FileDriver for ZipFileReader<'d, Io> { 126impl<'d, Io: Read> FileDriver for ZipFileReader<'d, Io> {
109 type Io = Io; 127 type Io = Io;
110 type FileInfo = ZipFileInfo; 128 type FileInfo = ZipFileInfo;
111
112 fn info(&self) -> &Self::FileInfo {
113 self.info
114 }
115} 129}
116 130
117impl<'d, Io: Read + Seek> ZipFileReader<'d, Io> { 131impl<'d, Io: Read + Seek> ZipFileReader<'d, Io> {
118 pub fn new(io: &'d mut Io, info: &'d ZipFileInfo, password: Option<&str>) -> ZipResult<Self> { 132 pub(crate) fn new(
133 io: &'d mut Io,
134 info: &'d ZipFileInfo,
135 password: Option<&[u8]>,
136 ) -> ZipResult<Self> {
119 io.seek(SeekFrom::Start(info.header_pointer))?; 137 io.seek(SeekFrom::Start(info.header_pointer))?;
120 138
121 let buf = io.read_arr::<30>()?; 139 let buf = io.read_arr::<30>()?;
@@ -127,49 +145,23 @@ impl<'d, Io: Read + Seek> ZipFileReader<'d, Io> {
127 + u16::from_le_bytes(buf[26..28].try_into().unwrap()) as u64 145 + u16::from_le_bytes(buf[26..28].try_into().unwrap()) as u64
128 + u16::from_le_bytes(buf[28..30].try_into().unwrap()) as u64; 146 + u16::from_le_bytes(buf[28..30].try_into().unwrap()) as u64;
129 147
130 io.seek(SeekFrom::Start(data_pointer))?;
131
132 Ok(Self { 148 Ok(Self {
133 io: match info.compression_method { 149 io: Compression::new(
134 CompressionMethod::Lzma => { 150 Encryption::new(
135 let buf = io.read_arr::<9>()?; 151 IoCursor::new(io, data_pointer, data_pointer + info.compressed_size)?,
136 Compression::Xz(XzDecoder::new_stream( 152 info,
137 Encryption::new( 153 password,
138 IoCursor::new(
139 io,
140 data_pointer + 9,
141 data_pointer + info.compressed_size,
142 )?,
143 info.encryption_method,
144 password,
145 )?,
146 Stream::new_raw_decoder(
147 Filters::new().lzma1(
148 LzmaOptions::new()
149 .literal_context_bits((buf[4] % 9) as u32)
150 .literal_position_bits((buf[4] / 9 % 5) as u32)
151 .position_bits((buf[4] / 45) as u32)
152 .dict_size(
153 u32::from_le_bytes(buf[5..9].try_into().unwrap()).max(4096),
154 ),
155 ),
156 )
157 .unwrap(),
158 ))
159 }
160 _ => Compression::new(
161 Encryption::new(
162 IoCursor::new(io, data_pointer, data_pointer + info.compressed_size)?,
163 info.encryption_method,
164 password,
165 )?,
166 info.compression_method,
167 )?, 154 )?,
168 }, 155 info,
156 )?,
169 info, 157 info,
170 }) 158 })
171 } 159 }
172 160
161 pub fn info(&self) -> &ZipFileInfo {
162 self.info
163 }
164
173 pub fn is_seekable(&self) -> bool { 165 pub fn is_seekable(&self) -> bool {
174 match self.io { 166 match self.io {
175 Compression::Store(Encryption::None(..)) => true, 167 Compression::Store(Encryption::None(..)) => true,