aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorigorechek06 <me@igorek.dev>2024-08-10 17:58:14 +0900
committerigorechek06 <me@igorek.dev>2024-08-10 17:58:14 +0900
commit1bb400dcb258f135a3f92f6242e728f0475325c1 (patch)
treec71783ceaff073077b7f65705101932ca8f0bbf6
parent866516ac50851e2827e6aff0a98c444268c566ff (diff)
downloadarchivator-1bb400dcb258f135a3f92f6242e728f0475325c1.tar.gz
archivator-1bb400dcb258f135a3f92f6242e728f0475325c1.zip
Unify zip errors
-rw-r--r--src/zip/datetime.rs4
-rw-r--r--src/zip/driver.rs16
-rw-r--r--src/zip/error.rs68
-rw-r--r--src/zip/file/info.rs4
-rw-r--r--src/zip/file/read.rs14
-rw-r--r--tests/zip.rs2
6 files changed, 43 insertions, 65 deletions
diff --git a/src/zip/datetime.rs b/src/zip/datetime.rs
index a4b1b55..e101334 100644
--- a/src/zip/datetime.rs
+++ b/src/zip/datetime.rs
@@ -18,13 +18,13 @@ impl<Tz: TimeZone> DosDateTime<Tz> for DateTime<Tz> {
18 date as u32 >> 5 & 0xF, 18 date as u32 >> 5 & 0xF,
19 date as u32 & 0x1F, 19 date as u32 & 0x1F,
20 ) 20 )
21 .ok_or(ZipError::InvalidDate)? 21 .ok_or(ZipError::InvalidField("date"))?
22 .and_hms_opt( 22 .and_hms_opt(
23 (time as u32 >> 11) & 0x1F, 23 (time as u32 >> 11) & 0x1F,
24 (time as u32 >> 5) & 0x3F, 24 (time as u32 >> 5) & 0x3F,
25 (time as u32 & 0x1F) * 2, 25 (time as u32 & 0x1F) * 2,
26 ) 26 )
27 .ok_or(ZipError::InvalidTime)? 27 .ok_or(ZipError::InvalidField("time"))?
28 .and_local_timezone(tz) 28 .and_local_timezone(tz)
29 .unwrap()) 29 .unwrap())
30 } 30 }
diff --git a/src/zip/driver.rs b/src/zip/driver.rs
index 9dccfd0..81629dd 100644
--- a/src/zip/driver.rs
+++ b/src/zip/driver.rs
@@ -83,11 +83,11 @@ impl<Io: Read + Seek> ArchiveRead for Zip<Io> {
83 + io.read_vec( 83 + io.read_vec(
84 (limit as usize) 84 (limit as usize)
85 .checked_sub(18) 85 .checked_sub(18)
86 .ok_or(ZipError::EocdrNotFound)?, 86 .ok_or(ZipError::StructNotFound("Eocdr"))?,
87 )? 87 )?
88 .windows(4) 88 .windows(4)
89 .rposition(|v| v == EOCDR_SIGNATURE) 89 .rposition(|v| v == EOCDR_SIGNATURE)
90 .ok_or(ZipError::EocdrNotFound)? as u64; 90 .ok_or(ZipError::StructNotFound("Eocdr"))? as u64;
91 91
92 // Read eocdr 92 // Read eocdr
93 io.seek(SeekFrom::Start(pos + 4))?; 93 io.seek(SeekFrom::Start(pos + 4))?;
@@ -106,7 +106,7 @@ impl<Io: Read + Seek> ArchiveRead for Zip<Io> {
106 io.seek(SeekFrom::Start(eocdr64locator.eocdr64_pointer))?; 106 io.seek(SeekFrom::Start(eocdr64locator.eocdr64_pointer))?;
107 let buf = io.read_arr::<56>()?; 107 let buf = io.read_arr::<56>()?;
108 if buf[0..4] != EOCDR64_SIGNATURE { 108 if buf[0..4] != EOCDR64_SIGNATURE {
109 return Err(ZipError::InvalidEocdr64Signature); 109 return Err(ZipError::InvalidSignature("Eocdr64"));
110 } 110 }
111 let eocdr64: Eocdr64 = deserialize(&buf[4..]).unwrap(); 111 let eocdr64: Eocdr64 = deserialize(&buf[4..]).unwrap();
112 if eocdr64.cd_pointer + eocdr64.cd_size > eocdr64locator.eocdr64_pointer { 112 if eocdr64.cd_pointer + eocdr64.cd_size > eocdr64locator.eocdr64_pointer {
@@ -139,14 +139,14 @@ impl<Io: Read + Seek> ArchiveRead for Zip<Io> {
139 let buf = cd_reader.read_arr::<46>()?; 139 let buf = cd_reader.read_arr::<46>()?;
140 140
141 if buf[..4] != CDR_SIGNATURE { 141 if buf[..4] != CDR_SIGNATURE {
142 return Err(ZipError::InvalidCdrSignature); 142 return Err(ZipError::InvalidSignature("Cdr"));
143 } 143 }
144 let cdr: Cdr = deserialize(&buf[4..46]).unwrap(); 144 let cdr: Cdr = deserialize(&buf[4..46]).unwrap();
145 let bit_flag = BitFlag::new(cdr.bit_flag); 145 let bit_flag = BitFlag::new(cdr.bit_flag);
146 146
147 let name = cd_reader.read_vec(cdr.name_len as usize)?; 147 let name = cd_reader.read_vec(cdr.name_len as usize)?;
148 let name = if bit_flag.is_utf8() { 148 let name = if bit_flag.is_utf8() {
149 String::from_utf8(name).map_err(|_| ZipError::InvalidFileName)? 149 String::from_utf8(name).map_err(|_| ZipError::InvalidField("file_name"))?
150 } else { 150 } else {
151 String::from_cp437(name) 151 String::from_cp437(name)
152 }; 152 };
@@ -155,7 +155,7 @@ impl<Io: Read + Seek> ArchiveRead for Zip<Io> {
155 155
156 let comment = cd_reader.read_vec(cdr.comment_len as usize)?; 156 let comment = cd_reader.read_vec(cdr.comment_len as usize)?;
157 let comment = if bit_flag.is_utf8() { 157 let comment = if bit_flag.is_utf8() {
158 String::from_utf8(comment).map_err(|_| ZipError::InvalidFileComment)? 158 String::from_utf8(comment).map_err(|_| ZipError::InvalidField("file_comment"))?
159 } else { 159 } else {
160 String::from_cp437(comment) 160 String::from_cp437(comment)
161 }; 161 };
@@ -216,7 +216,7 @@ impl<Io: Read + Seek> ArchiveRead for Zip<Io> {
216 0x9901 => { 216 0x9901 => {
217 let aes: AesField = deserialize(&data.read_arr::<7>()?).unwrap(); 217 let aes: AesField = deserialize(&data.read_arr::<7>()?).unwrap();
218 if aes.id != [0x41, 0x45] { 218 if aes.id != [0x41, 0x45] {
219 return Err(ZipError::InvalidExtraFields); 219 return Err(ZipError::InvalidField("extra_fields"));
220 } 220 }
221 encryption_method = match aes.strength { 221 encryption_method = match aes.strength {
222 0x01 => EncryptionMethod::Aes128, 222 0x01 => EncryptionMethod::Aes128,
@@ -232,7 +232,7 @@ impl<Io: Read + Seek> ArchiveRead for Zip<Io> {
232 } 232 }
233 233
234 if compression_method == 99 { 234 if compression_method == 99 {
235 return Err(ZipError::AesExtraFieldNotFound); 235 return Err(ZipError::StructNotFound("AesExtensibleData"));
236 } 236 }
237 237
238 indexes.insert(name.clone(), i); 238 indexes.insert(name.clone(), i);
diff --git a/src/zip/error.rs b/src/zip/error.rs
index dbb6bb5..fbc2ba1 100644
--- a/src/zip/error.rs
+++ b/src/zip/error.rs
@@ -8,27 +8,18 @@ pub type ZipResult<T> = Result<T, ZipError>;
8pub enum ZipError { 8pub enum ZipError {
9 Io(IoError), 9 Io(IoError),
10 10
11 EocdrNotFound, 11 // Driver errors
12 InvalidEocdr64Signature, 12 StructNotFound(&'static str),
13 InvalidFileHeaderSignature, 13 InvalidSignature(&'static str),
14 InvalidCdrSignature, 14 InvalidField(&'static str),
15 15 Unsupported(&'static str),
16 Overlapping(&'static str, &'static str), 16 Overlapping(&'static str, &'static str),
17 17
18 UnsupportedCompressionMethod(u16), 18 // API errors
19 UnsupportedEncryptionMethod,
20 InvalidDate,
21 InvalidTime,
22 InvalidFileName,
23 InvalidExtraFields,
24 AesExtraFieldNotFound,
25 InvalidFileComment,
26
27 FileNotFound, 19 FileNotFound,
28 WrongPassword, 20 WrongPassword,
29 PasswordIsNotSpecified, 21 PasswordIsNotSpecified,
30 CompressedDataIsUnseekable, 22 UnseekableFile,
31 EncryptedDataIsUnseekable,
32} 23}
33 24
34impl From<IoError> for ZipError { 25impl From<IoError> for ZipError {
@@ -41,9 +32,10 @@ impl PartialEq for ZipError {
41 fn eq(&self, other: &Self) -> bool { 32 fn eq(&self, other: &Self) -> bool {
42 match (self, other) { 33 match (self, other) {
43 (Self::Io(l0), Self::Io(r0)) => l0.kind() == r0.kind(), 34 (Self::Io(l0), Self::Io(r0)) => l0.kind() == r0.kind(),
44 (Self::UnsupportedCompressionMethod(l0), Self::UnsupportedCompressionMethod(r0)) => { 35 (Self::StructNotFound(l0), Self::StructNotFound(r0)) => l0 == r0,
45 l0 == r0 36 (Self::InvalidSignature(l0), Self::InvalidSignature(r0)) => l0 == r0,
46 } 37 (Self::InvalidField(l0), Self::InvalidField(r0)) => l0 == r0,
38 (Self::Overlapping(l0, l1), Self::Overlapping(r0, r1)) => l0 == r0 && l1 == r1,
47 _ => core::mem::discriminant(self) == core::mem::discriminant(other), 39 _ => core::mem::discriminant(self) == core::mem::discriminant(other),
48 } 40 }
49 } 41 }
@@ -56,42 +48,26 @@ impl Display for ZipError {
56 match self { 48 match self {
57 Self::Io(error) => write!(f, "{}", error), 49 Self::Io(error) => write!(f, "{}", error),
58 50
59 Self::EocdrNotFound => write!(f, "End of central directory record not found"), 51 Self::StructNotFound(struct_name) => {
60 Self::InvalidEocdr64Signature => { 52 write!(f, "Struct '{}' not found", struct_name)
61 write!(
62 f,
63 "Invalid signature of zip64 end of central directory record"
64 )
65 } 53 }
66 Self::InvalidFileHeaderSignature => { 54 Self::InvalidSignature(struct_name) => {
67 write!(f, "Invalid file header signature") 55 write!(f, "Invalid signature of struct '{}'", struct_name)
68 } 56 }
69 Self::InvalidCdrSignature => { 57 Self::InvalidField(field_name) => {
70 write!(f, "Invalid signature of central directory record") 58 write!(f, "Field '{}' has invalid data", field_name)
71 } 59 }
72 60 Self::Unsupported(data_type) => {
73 Self::Overlapping(struct1, struct2) => { 61 writeln!(f, "Unsupported {}", data_type)
74 write!(f, "`{}` overlapt `{}`", struct1, struct2)
75 }
76
77 Self::UnsupportedCompressionMethod(id) => {
78 writeln!(f, "Unsupported compression method `{}`", id)
79 } 62 }
80 Self::UnsupportedEncryptionMethod => { 63 Self::Overlapping(struct_name1, struct_name2) => {
81 writeln!(f, "Unsupported encryption method") 64 write!(f, "`{}` overlap `{}`", struct_name1, struct_name2)
82 } 65 }
83 Self::InvalidDate => write!(f, "Invalid date"),
84 Self::InvalidTime => write!(f, "Invalid time"),
85 Self::InvalidFileName => write!(f, "Invalid file name"),
86 Self::InvalidExtraFields => write!(f, "Invalid extra fields"),
87 Self::AesExtraFieldNotFound => write!(f, "Aes extra field not found"),
88 Self::InvalidFileComment => write!(f, "Invalid file comment"),
89 66
90 Self::FileNotFound => write!(f, "File not found"), 67 Self::FileNotFound => write!(f, "File not found"),
91 Self::WrongPassword => write!(f, "Wrong password"), 68 Self::WrongPassword => write!(f, "Wrong password"),
92 Self::PasswordIsNotSpecified => write!(f, "Password is not specified"), 69 Self::PasswordIsNotSpecified => write!(f, "Password is not specified"),
93 Self::CompressedDataIsUnseekable => write!(f, "Compressed data is unseekable"), 70 Self::UnseekableFile => write!(f, "File is unseekable"),
94 Self::EncryptedDataIsUnseekable => write!(f, "Encrypted data is unseekable"),
95 } 71 }
96 } 72 }
97} 73}
diff --git a/src/zip/file/info.rs b/src/zip/file/info.rs
index 38ea984..93b9f43 100644
--- a/src/zip/file/info.rs
+++ b/src/zip/file/info.rs
@@ -10,7 +10,7 @@ pub enum CompressionMethod {
10 Lzma, 10 Lzma,
11 Zstd, 11 Zstd,
12 Xz, 12 Xz,
13 Unsupported(u16), 13 Unsupported,
14} 14}
15 15
16impl CompressionMethod { 16impl CompressionMethod {
@@ -23,7 +23,7 @@ impl CompressionMethod {
23 14 => Self::Lzma, 23 14 => Self::Lzma,
24 93 => Self::Zstd, 24 93 => Self::Zstd,
25 95 => Self::Xz, 25 95 => Self::Xz,
26 _ => Self::Unsupported(id), 26 _ => Self::Unsupported,
27 } 27 }
28 } 28 }
29} 29}
diff --git a/src/zip/file/read.rs b/src/zip/file/read.rs
index d25655e..567fb75 100644
--- a/src/zip/file/read.rs
+++ b/src/zip/file/read.rs
@@ -116,7 +116,9 @@ impl<Io: Read + Seek> Encryption<IoCursor<Io>> {
116 Aes256::new(key.into()), 116 Aes256::new(key.into()),
117 )?) 117 )?)
118 } 118 }
119 EncryptionMethod::Unsupported => return Err(ZipError::UnsupportedEncryptionMethod), 119 EncryptionMethod::Unsupported => {
120 return Err(ZipError::Unsupported("encryption method"))
121 }
120 }) 122 })
121 } 123 }
122} 124}
@@ -141,7 +143,7 @@ impl<Io: Read + Seek> Seek for Encryption<Io> {
141 Self::None(io) => io.seek(pos), 143 Self::None(io) => io.seek(pos),
142 _ => Err(IoError::new( 144 _ => Err(IoError::new(
143 IoErrorKind::Unsupported, 145 IoErrorKind::Unsupported,
144 ZipError::EncryptedDataIsUnseekable, 146 ZipError::UnseekableFile,
145 )), 147 )),
146 } 148 }
147 } 149 }
@@ -182,8 +184,8 @@ impl<Io: Read + Seek> Compression<Io> {
182 } 184 }
183 CompressionMethod::Zstd => Self::Zstd(ZstdDecoder::new(io)?), 185 CompressionMethod::Zstd => Self::Zstd(ZstdDecoder::new(io)?),
184 CompressionMethod::Xz => Self::Xz(XzDecoder::new(io)), 186 CompressionMethod::Xz => Self::Xz(XzDecoder::new(io)),
185 CompressionMethod::Unsupported(id) => { 187 CompressionMethod::Unsupported => {
186 return Err(ZipError::UnsupportedCompressionMethod(id)) 188 return Err(ZipError::Unsupported("compression method"));
187 } 189 }
188 }) 190 })
189 } 191 }
@@ -209,7 +211,7 @@ impl<Io: Read + Seek> Seek for Compression<Io> {
209 Compression::Store(io) => io.seek(pos), 211 Compression::Store(io) => io.seek(pos),
210 _ => Err(IoError::new( 212 _ => Err(IoError::new(
211 IoErrorKind::Unsupported, 213 IoErrorKind::Unsupported,
212 ZipError::CompressedDataIsUnseekable, 214 ZipError::UnseekableFile,
213 )), 215 )),
214 } 216 }
215 } 217 }
@@ -235,7 +237,7 @@ impl<'d, Io: Read + Seek> ZipFileReader<'d, Io> {
235 237
236 let buf = io.read_arr::<30>()?; 238 let buf = io.read_arr::<30>()?;
237 if buf[..4] != FILE_HEADER_SIGNATURE { 239 if buf[..4] != FILE_HEADER_SIGNATURE {
238 return Err(ZipError::InvalidFileHeaderSignature); 240 return Err(ZipError::InvalidSignature("FileHeader"));
239 } 241 }
240 242
241 let cursor = io.seek(SeekFrom::Start( 243 let cursor = io.seek(SeekFrom::Start(
diff --git a/tests/zip.rs b/tests/zip.rs
index e44098c..e2b5c20 100644
--- a/tests/zip.rs
+++ b/tests/zip.rs
@@ -164,5 +164,5 @@ fn test_zip() {
164#[test] 164#[test]
165fn test_bad_zip() { 165fn test_bad_zip() {
166 assert!(Archive::<Zip>::read_from_file("tests/files/blank") 166 assert!(Archive::<Zip>::read_from_file("tests/files/blank")
167 .is_err_and(|e| e == ZipError::EocdrNotFound)); 167 .is_err_and(|e| e == ZipError::StructNotFound("Eocdr")));
168} 168}