aboutsummaryrefslogtreecommitdiff
path: root/src/zip/driver.rs
diff options
context:
space:
mode:
authorIgor Tolmachev <me@igorek.dev>2024-07-16 21:15:38 +0900
committerIgor Tolmachev <me@igorek.dev>2024-07-16 21:15:38 +0900
commit2f0f96ce4625d2ef1273c7bea98a1e9415419fdf (patch)
tree42104b66f80e8b2ad3d831538b8e32c02d1cf97e /src/zip/driver.rs
parent9c0e544e79a4f7874dab449674a11d899bf61963 (diff)
downloadarchivator-2f0f96ce4625d2ef1273c7bea98a1e9415419fdf.tar.gz
archivator-2f0f96ce4625d2ef1273c7bea98a1e9415419fdf.zip
Add BufReader for CD records parser
Diffstat (limited to 'src/zip/driver.rs')
-rw-r--r--src/zip/driver.rs35
1 files changed, 18 insertions, 17 deletions
diff --git a/src/zip/driver.rs b/src/zip/driver.rs
index 631c4ed..e7878cf 100644
--- a/src/zip/driver.rs
+++ b/src/zip/driver.rs
@@ -9,7 +9,7 @@ use crate::zip::{
9use chrono::{DateTime, Local, NaiveDate, NaiveDateTime, NaiveTime}; 9use chrono::{DateTime, Local, NaiveDate, NaiveDateTime, NaiveTime};
10use std::collections::HashMap as Map; 10use std::collections::HashMap as Map;
11use std::fs::File; 11use std::fs::File;
12use std::io::{Read, Seek, SeekFrom, Write}; 12use std::io::{BufReader, Read, Seek, SeekFrom, Write};
13 13
14fn dos_to_local(date: u16, time: u16) -> ZipResult<DateTime<Local>> { 14fn dos_to_local(date: u16, time: u16) -> ZipResult<DateTime<Local>> {
15 Ok(NaiveDateTime::new( 15 Ok(NaiveDateTime::new(
@@ -111,33 +111,32 @@ impl<Io: Read + Seek> ArchiveRead for Zip<Io> {
111 let mut indexes = Map::with_capacity(cd_records as usize); 111 let mut indexes = Map::with_capacity(cd_records as usize);
112 let mut files = Vec::with_capacity(cd_records as usize); 112 let mut files = Vec::with_capacity(cd_records as usize);
113 io.seek(SeekFrom::Start(cd_pointer))?; 113 io.seek(SeekFrom::Start(cd_pointer))?;
114 let buf = io.read_vec(cd_size as usize)?; 114 let mut buf_reader = BufReader::with_capacity(cd_size.min(131072) as usize, &mut io);
115 115
116 let mut p: usize = 0;
117 for i in 0..cd_records as usize { 116 for i in 0..cd_records as usize {
118 if u32::from_le_bytes(buf[p..p + 4].try_into().unwrap()) != 0x02014b50 { 117 let buf = buf_reader.read_arr::<46>()?;
118
119 if u32::from_le_bytes(buf[..4].try_into().unwrap()) != 0x02014b50 {
119 return Err(ZipError::InvalidCDRSignature.into()); 120 return Err(ZipError::InvalidCDRSignature.into());
120 } 121 }
121 p += 4; 122 let cdr: Cdr = deserialize(&buf[4..46]).unwrap();
122 let cdr: Cdr = deserialize(&buf[p..p + 42]).unwrap();
123 let bit_flag = BitFlag::new(cdr.bit_flag); 123 let bit_flag = BitFlag::new(cdr.bit_flag);
124 p += 42; 124
125 let name = buf_reader.read_vec(cdr.name_len as usize)?;
125 let name = if bit_flag.is_utf8() { 126 let name = if bit_flag.is_utf8() {
126 String::from_utf8(buf[p..p + cdr.name_len as usize].to_vec()) 127 String::from_utf8(name).map_err(|_| ZipError::InvalidFileName)?
127 .map_err(|_| ZipError::InvalidFileName)?
128 } else { 128 } else {
129 String::from_cp437(&buf[p..p + cdr.name_len as usize]) 129 String::from_cp437(name)
130 }; 130 };
131 p += cdr.name_len as usize; 131
132 let extra_fields: Vec<u8> = buf[p..p + cdr.extra_field_len as usize].into(); 132 let extra_fields = buf_reader.read_vec(cdr.extra_field_len as usize)?;
133 p += cdr.extra_field_len as usize; 133
134 let comment = buf_reader.read_vec(cdr.comment_len as usize)?;
134 let comment = if bit_flag.is_utf8() { 135 let comment = if bit_flag.is_utf8() {
135 String::from_utf8(buf[p..p + cdr.comment_len as usize].to_vec()) 136 String::from_utf8(comment).map_err(|_| ZipError::InvalidFileComment)?
136 .map_err(|_| ZipError::InvalidFileComment)?
137 } else { 137 } else {
138 String::from_cp437(&buf[p..p + cdr.comment_len as usize]) 138 String::from_cp437(comment)
139 }; 139 };
140 p += cdr.comment_len as usize;
141 140
142 let mut compressed_size = cdr.compressed_size as u64; 141 let mut compressed_size = cdr.compressed_size as u64;
143 let mut size = cdr.size as u64; 142 let mut size = cdr.size as u64;
@@ -152,6 +151,7 @@ impl<Io: Read + Seek> ArchiveRead for Zip<Io> {
152 while ep < cdr.extra_field_len as usize { 151 while ep < cdr.extra_field_len as usize {
153 let header: ExtraHeader = deserialize(&extra_fields[ep..ep + 4]).unwrap(); 152 let header: ExtraHeader = deserialize(&extra_fields[ep..ep + 4]).unwrap();
154 ep += 4; 153 ep += 4;
154
155 match header.id { 155 match header.id {
156 // Zip64 156 // Zip64
157 0x0001 => { 157 0x0001 => {
@@ -182,6 +182,7 @@ impl<Io: Read + Seek> ArchiveRead for Zip<Io> {
182 let header: ExtraHeader = 182 let header: ExtraHeader =
183 deserialize(&extra_fields[tp..tp + 4]).unwrap(); 183 deserialize(&extra_fields[tp..tp + 4]).unwrap();
184 tp += 4; 184 tp += 4;
185
185 match header.id { 186 match header.id {
186 0x0001 => { 187 0x0001 => {
187 mtime = ntfs_to_local(u64::from_le_bytes( 188 mtime = ntfs_to_local(u64::from_le_bytes(