diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/zip/driver.rs | 35 |
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::{ | |||
| 9 | use chrono::{DateTime, Local, NaiveDate, NaiveDateTime, NaiveTime}; | 9 | use chrono::{DateTime, Local, NaiveDate, NaiveDateTime, NaiveTime}; |
| 10 | use std::collections::HashMap as Map; | 10 | use std::collections::HashMap as Map; |
| 11 | use std::fs::File; | 11 | use std::fs::File; |
| 12 | use std::io::{Read, Seek, SeekFrom, Write}; | 12 | use std::io::{BufReader, Read, Seek, SeekFrom, Write}; |
| 13 | 13 | ||
| 14 | fn dos_to_local(date: u16, time: u16) -> ZipResult<DateTime<Local>> { | 14 | fn 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( |
