Skip to content

Commit c83e9b6

Browse files
Revert "remove the old ZipFile API entirely"
This reverts commit f0faf24.
1 parent 423a263 commit c83e9b6

15 files changed

Lines changed: 894 additions & 98 deletions

benches/merge_archive.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ fn perform_raw_copy_file<R: Read + Seek, W: Write + Seek>(
4141
mut target: ZipWriter<W>,
4242
) -> ZipResult<ZipWriter<W>> {
4343
for i in 0..src.len() {
44-
let entry = src.by_index_raw(i)?;
45-
target.copy_file(entry)?;
44+
let entry = src.by_index(i)?;
45+
target.raw_copy_file(entry)?;
4646
}
4747
Ok(target)
4848
}

examples/extract.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
use std::fs;
22
use std::io;
33

4-
use zip::unstable::read::ArchiveEntry;
5-
64
fn main() {
75
std::process::exit(real_main());
86
}

examples/file_info.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
use std::fs;
22
use std::io::BufReader;
33

4-
use zip::unstable::read::ArchiveEntry;
5-
64
fn main() {
75
std::process::exit(real_main());
86
}

src/crc32.rs

Lines changed: 159 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,25 @@ pub struct Crc32Reader<R> {
1010
inner: R,
1111
hasher: Hasher,
1212
check: u32,
13+
/// Signals if `inner` stores aes encrypted data.
14+
/// AE-2 encrypted data doesn't use crc and sets the value to 0.
15+
enabled: bool,
1316
}
1417

1518
impl<R> Crc32Reader<R> {
1619
/// Get a new Crc32Reader which checks the inner reader against checksum.
17-
pub(crate) fn new(inner: R, checksum: u32) -> Self {
20+
/// The check is disabled if `ae2_encrypted == true`.
21+
pub(crate) fn new(inner: R, checksum: u32, ae2_encrypted: bool) -> Crc32Reader<R> {
1822
Crc32Reader {
1923
inner,
2024
hasher: Hasher::new(),
2125
check: checksum,
26+
enabled: !ae2_encrypted,
2227
}
2328
}
2429

25-
fn check_matches(&self) -> Result<(), &'static str> {
26-
let res = self.hasher.clone().finalize();
27-
if self.check == res {
28-
Ok(())
29-
} else {
30-
/* TODO: make this into our own Crc32Error error type! */
31-
Err("Invalid checksum")
32-
}
30+
fn check_matches(&self) -> bool {
31+
self.check == self.hasher.clone().finalize()
3332
}
3433

3534
#[allow(dead_code)]
@@ -38,27 +37,159 @@ impl<R> Crc32Reader<R> {
3837
}
3938
}
4039

40+
#[cold]
41+
fn invalid_checksum() -> io::Error {
42+
io::Error::new(io::ErrorKind::InvalidData, "Invalid checksum")
43+
}
44+
4145
impl<R: Read> Read for Crc32Reader<R> {
4246
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
43-
/* We want to make sure we only check the hash when the input stream is exhausted. */
44-
if buf.is_empty() {
45-
/* If the input buf is empty (this shouldn't happen, but isn't guaranteed), we
46-
* still want to "pull" from the source in case it surfaces an i/o error. This will
47-
* always return a count of Ok(0) if successful. */
48-
return self.inner.read(buf);
49-
}
50-
5147
let count = self.inner.read(buf)?;
52-
if count == 0 {
53-
return self
54-
.check_matches()
55-
.map(|()| 0)
56-
/* TODO: use io::Error::other for MSRV >=1.74 */
57-
.map_err(|e| io::Error::new(io::ErrorKind::Other, e));
48+
49+
if self.enabled {
50+
if count == 0 && !buf.is_empty() && !self.check_matches() {
51+
return Err(invalid_checksum());
52+
}
53+
self.hasher.update(&buf[..count]);
5854
}
59-
self.hasher.update(&buf[..count]);
6055
Ok(count)
6156
}
57+
58+
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
59+
let start = buf.len();
60+
let n = self.inner.read_to_end(buf)?;
61+
62+
if self.enabled {
63+
self.hasher.update(&buf[start..]);
64+
if !self.check_matches() {
65+
return Err(invalid_checksum());
66+
}
67+
}
68+
69+
Ok(n)
70+
}
71+
72+
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
73+
let start = buf.len();
74+
let n = self.inner.read_to_string(buf)?;
75+
76+
if self.enabled {
77+
self.hasher.update(&buf.as_bytes()[start..]);
78+
if !self.check_matches() {
79+
return Err(invalid_checksum());
80+
}
81+
}
82+
83+
Ok(n)
84+
}
85+
}
86+
87+
pub(crate) mod non_crypto {
88+
use std::io;
89+
use std::io::prelude::*;
90+
91+
use crc32fast::Hasher;
92+
93+
/// Reader that validates the CRC32 when it reaches the EOF.
94+
pub struct Crc32Reader<R> {
95+
inner: R,
96+
hasher: Hasher,
97+
check: u32,
98+
}
99+
100+
impl<R> Crc32Reader<R> {
101+
/// Get a new Crc32Reader which checks the inner reader against checksum.
102+
pub(crate) fn new(inner: R, checksum: u32) -> Self {
103+
Crc32Reader {
104+
inner,
105+
hasher: Hasher::new(),
106+
check: checksum,
107+
}
108+
}
109+
110+
fn check_matches(&self) -> Result<(), &'static str> {
111+
let res = self.hasher.clone().finalize();
112+
if self.check == res {
113+
Ok(())
114+
} else {
115+
/* TODO: make this into our own Crc32Error error type! */
116+
Err("Invalid checksum")
117+
}
118+
}
119+
120+
pub fn into_inner(self) -> R {
121+
self.inner
122+
}
123+
}
124+
125+
impl<R: Read> Read for Crc32Reader<R> {
126+
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
127+
/* We want to make sure we only check the hash when the input stream is exhausted. */
128+
if buf.is_empty() {
129+
/* If the input buf is empty (this shouldn't happen, but isn't guaranteed), we
130+
* still want to "pull" from the source in case it surfaces an i/o error. This will
131+
* always return a count of Ok(0) if successful. */
132+
return self.inner.read(buf);
133+
}
134+
135+
let count = self.inner.read(buf)?;
136+
if count == 0 {
137+
return self
138+
.check_matches()
139+
.map(|()| 0)
140+
/* TODO: use io::Error::other for MSRV >=1.74 */
141+
.map_err(|e| io::Error::new(io::ErrorKind::Other, e));
142+
}
143+
self.hasher.update(&buf[..count]);
144+
Ok(count)
145+
}
146+
}
147+
148+
#[cfg(test)]
149+
mod test {
150+
use super::*;
151+
152+
#[test]
153+
fn test_empty_reader() {
154+
let data: &[u8] = b"";
155+
let mut buf = [0; 1];
156+
157+
let mut reader = Crc32Reader::new(data, 0);
158+
assert_eq!(reader.read(&mut buf).unwrap(), 0);
159+
160+
let mut reader = Crc32Reader::new(data, 1);
161+
assert!(reader
162+
.read(&mut buf)
163+
.unwrap_err()
164+
.to_string()
165+
.contains("Invalid checksum"));
166+
}
167+
168+
#[test]
169+
fn test_byte_by_byte() {
170+
let data: &[u8] = b"1234";
171+
let mut buf = [0; 1];
172+
173+
let mut reader = Crc32Reader::new(data, 0x9be3e0a3);
174+
assert_eq!(reader.read(&mut buf).unwrap(), 1);
175+
assert_eq!(reader.read(&mut buf).unwrap(), 1);
176+
assert_eq!(reader.read(&mut buf).unwrap(), 1);
177+
assert_eq!(reader.read(&mut buf).unwrap(), 1);
178+
assert_eq!(reader.read(&mut buf).unwrap(), 0);
179+
// Can keep reading 0 bytes after the end
180+
assert_eq!(reader.read(&mut buf).unwrap(), 0);
181+
}
182+
183+
#[test]
184+
fn test_zero_read() {
185+
let data: &[u8] = b"1234";
186+
let mut buf = [0; 5];
187+
188+
let mut reader = Crc32Reader::new(data, 0x9be3e0a3);
189+
assert_eq!(reader.read(&mut buf[..0]).unwrap(), 0);
190+
assert_eq!(reader.read(&mut buf).unwrap(), 4);
191+
}
192+
}
62193
}
63194

64195
#[cfg(test)]
@@ -70,10 +201,10 @@ mod test {
70201
let data: &[u8] = b"";
71202
let mut buf = [0; 1];
72203

73-
let mut reader = Crc32Reader::new(data, 0);
204+
let mut reader = Crc32Reader::new(data, 0, false);
74205
assert_eq!(reader.read(&mut buf).unwrap(), 0);
75206

76-
let mut reader = Crc32Reader::new(data, 1);
207+
let mut reader = Crc32Reader::new(data, 1, false);
77208
assert!(reader
78209
.read(&mut buf)
79210
.unwrap_err()
@@ -86,7 +217,7 @@ mod test {
86217
let data: &[u8] = b"1234";
87218
let mut buf = [0; 1];
88219

89-
let mut reader = Crc32Reader::new(data, 0x9be3e0a3);
220+
let mut reader = Crc32Reader::new(data, 0x9be3e0a3, false);
90221
assert_eq!(reader.read(&mut buf).unwrap(), 1);
91222
assert_eq!(reader.read(&mut buf).unwrap(), 1);
92223
assert_eq!(reader.read(&mut buf).unwrap(), 1);
@@ -101,7 +232,7 @@ mod test {
101232
let data: &[u8] = b"1234";
102233
let mut buf = [0; 5];
103234

104-
let mut reader = Crc32Reader::new(data, 0x9be3e0a3);
235+
let mut reader = Crc32Reader::new(data, 0x9be3e0a3, false);
105236
assert_eq!(reader.read(&mut buf[..0]).unwrap(), 0);
106237
assert_eq!(reader.read(&mut buf).unwrap(), 4);
107238
}

0 commit comments

Comments
 (0)