Lots of additions
This commit is contained in:
parent
70c82e411f
commit
1cbc1e9e6a
2 changed files with 167 additions and 25 deletions
|
@ -2,8 +2,12 @@ extern crate zip;
|
|||
|
||||
fn main()
|
||||
{
|
||||
let mut stdin = std::io::stdin();
|
||||
let header = zip::spec::LocalFileHeader::parse(&mut stdin).unwrap();
|
||||
let args = std::os::args();
|
||||
let fname = Path::new(args[1].as_slice());
|
||||
let mut file = std::io::File::open(&fname);
|
||||
|
||||
let header = zip::spec::LocalFileHeader::parse(&mut file).unwrap();
|
||||
println!("{}", header);
|
||||
println!("{}", String::from_utf8(header.file_name));
|
||||
println!("{:x}", header.crc32);
|
||||
println!("{}", String::from_utf8(header.file_name.clone()));
|
||||
}
|
||||
|
|
182
src/spec.rs
182
src/spec.rs
|
@ -3,24 +3,10 @@ use std::io::{IoResult, IoError};
|
|||
use time::Tm;
|
||||
use util;
|
||||
|
||||
/*
|
||||
4.3.7 Local file header:
|
||||
|
||||
local file header signature 4 bytes (0x04034b50)
|
||||
version needed to extract 2 bytes
|
||||
general purpose bit flag 2 bytes
|
||||
compression method 2 bytes
|
||||
last mod file time 2 bytes
|
||||
last mod file date 2 bytes
|
||||
crc-32 4 bytes
|
||||
compressed size 4 bytes
|
||||
uncompressed size 4 bytes
|
||||
file name length 2 bytes
|
||||
extra field length 2 bytes
|
||||
|
||||
file name (variable size)
|
||||
extra field (variable size)
|
||||
*/
|
||||
static LOCAL_FILE_HEADER_SIGNATURE : u32 = 0x04034b50;
|
||||
static DATA_DESCRIPTOR_SIGNATURE : u32 = 0x08074b50;
|
||||
static CENTRAL_DIRECTORY_HEADER_SIGNATURE : u32 = 0x02014b50;
|
||||
static DIGITAL_SIGNATURE_SIGNATURE : u32 = 0x05054b50;
|
||||
|
||||
#[deriving(FromPrimitive, Show)]
|
||||
pub enum CompressionMethod
|
||||
|
@ -64,20 +50,27 @@ pub struct LocalFileHeader
|
|||
|
||||
compression_method: CompressionMethod,
|
||||
last_modified: Tm,
|
||||
crc32: u32,
|
||||
pub crc32: u32,
|
||||
compressed_size: u32,
|
||||
uncompressed_size: u32,
|
||||
pub file_name: Vec<u8>,
|
||||
extra_field: Vec<u8>,
|
||||
header_end: u64,
|
||||
}
|
||||
|
||||
|
||||
impl LocalFileHeader
|
||||
{
|
||||
pub fn parse<T: Reader>(reader: &mut T) -> IoResult<LocalFileHeader>
|
||||
pub fn parse<T: Reader+Seek>(reader: &mut T) -> IoResult<LocalFileHeader>
|
||||
{
|
||||
let magic = try!(reader.read_le_u32());
|
||||
if magic != 0x04034b50 { return Err(IoError { kind: io::MismatchedFileTypeForOperation, desc: "Invalid local file header", detail: None }) }
|
||||
let signature = try!(reader.read_le_u32());
|
||||
if signature != LOCAL_FILE_HEADER_SIGNATURE
|
||||
{
|
||||
return Err(IoError {
|
||||
kind: io::MismatchedFileTypeForOperation,
|
||||
desc: "Invalid local file header",
|
||||
detail: None })
|
||||
}
|
||||
let version = try!(reader.read_le_u16());
|
||||
let flags = try!(reader.read_le_u16());
|
||||
let compression_method = try!(reader.read_le_u16());
|
||||
|
@ -90,6 +83,7 @@ impl LocalFileHeader
|
|||
let extra_field_length = try!(reader.read_le_u16());
|
||||
let file_name = try!(reader.read_exact(file_name_length as uint));
|
||||
let extra_field = try!(reader.read_exact(extra_field_length as uint));
|
||||
let header_end = try!(reader.tell());
|
||||
|
||||
Ok(LocalFileHeader
|
||||
{
|
||||
|
@ -107,6 +101,150 @@ impl LocalFileHeader
|
|||
uncompressed_size: uncompressed_size,
|
||||
file_name: file_name,
|
||||
extra_field: extra_field,
|
||||
header_end: header_end,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct DataDescriptor
|
||||
{
|
||||
compressed_size: u32,
|
||||
uncompressed_size: u32,
|
||||
crc32: u32,
|
||||
}
|
||||
|
||||
impl DataDescriptor
|
||||
{
|
||||
pub fn parse<T: Reader>(reader: &mut T) -> IoResult<DataDescriptor>
|
||||
{
|
||||
let first = try!(reader.read_le_u32());
|
||||
let compressed = if first == DATA_DESCRIPTOR_SIGNATURE
|
||||
{
|
||||
try!(reader.read_le_u32())
|
||||
}
|
||||
else
|
||||
{
|
||||
first
|
||||
};
|
||||
|
||||
let uncompressed = try!(reader.read_le_u32());
|
||||
let crc = try!(reader.read_le_u32());
|
||||
|
||||
Ok(DataDescriptor
|
||||
{
|
||||
compressed_size: compressed,
|
||||
uncompressed_size: uncompressed,
|
||||
crc32: crc,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct CentralDirectoryHeader
|
||||
{
|
||||
made_by: u16,
|
||||
version_needed: u16,
|
||||
|
||||
// general purpose flags
|
||||
encrypted: bool, // bit 0
|
||||
// bit 1 & 2 unused
|
||||
has_descriptor: bool, // bit 3
|
||||
// bit 4 unused
|
||||
is_compressed_patch: bool, // bit 5
|
||||
strong_encryption: bool, // bit 6
|
||||
// bit 7 - 10 unused
|
||||
is_utf8: bool, // bit 11
|
||||
// bit 12 unused
|
||||
is_masked: bool, // bit 13
|
||||
// bit 14 & 15 unused
|
||||
|
||||
compression_method: CompressionMethod,
|
||||
last_modified_time: Tm,
|
||||
crc32: u32,
|
||||
compressed_size: u32,
|
||||
uncompressed_size: u32,
|
||||
file_name: Vec<u8>,
|
||||
extra_field: Vec<u8>,
|
||||
file_comment: Vec<u8>,
|
||||
disk_number: u16,
|
||||
file_offset: u32,
|
||||
}
|
||||
|
||||
impl CentralDirectoryHeader
|
||||
{
|
||||
pub fn parse<T: Reader>(reader: &mut T) -> IoResult<CentralDirectoryHeader>
|
||||
{
|
||||
let signature = try!(reader.read_le_u32());
|
||||
if signature != CENTRAL_DIRECTORY_HEADER_SIGNATURE
|
||||
{
|
||||
return Err(IoError {
|
||||
kind: io::MismatchedFileTypeForOperation,
|
||||
desc: "Invalid central directory header",
|
||||
detail: None })
|
||||
}
|
||||
|
||||
let made_by = try!(reader.read_le_u16());
|
||||
let version_needed = try!(reader.read_le_u16());
|
||||
let flags = try!(reader.read_le_u16());
|
||||
let compression = try!(reader.read_le_u16());
|
||||
let last_mod_time = try!(reader.read_le_u16());
|
||||
let last_mod_date = try!(reader.read_le_u16());
|
||||
let crc = try!(reader.read_le_u32());
|
||||
let compressed_size = try!(reader.read_le_u32());
|
||||
let uncompressed_size = try!(reader.read_le_u32());
|
||||
let file_name_length = try!(reader.read_le_u16()) as uint;
|
||||
let extra_field_length = try!(reader.read_le_u16()) as uint;
|
||||
let file_comment_length = try!(reader.read_le_u16()) as uint;
|
||||
let disk_number = try!(reader.read_le_u16());
|
||||
try!(reader.read_le_u16()); // internal file attribute
|
||||
try!(reader.read_le_u32()); // external file attribute
|
||||
let offset = try!(reader.read_le_u32());
|
||||
let file_name = try!(reader.read_exact(file_name_length));
|
||||
let extra_field = try!(reader.read_exact(extra_field_length));
|
||||
let file_comment = try!(reader.read_exact(file_comment_length));
|
||||
|
||||
Ok(CentralDirectoryHeader
|
||||
{
|
||||
made_by: made_by,
|
||||
version_needed: version_needed,
|
||||
encrypted: flags & (1 << 0) != 0,
|
||||
has_descriptor: flags & (1 << 3) != 0,
|
||||
is_compressed_patch: flags & (1 << 5) != 0,
|
||||
strong_encryption: flags & (1 << 6) != 0,
|
||||
is_utf8: flags & (1 << 11) != 0,
|
||||
is_masked: flags & (1 << 13) != 0,
|
||||
compression_method: FromPrimitive::from_u16(compression).unwrap_or(Unknown),
|
||||
last_modified_time: util::msdos_datetime_to_tm(last_mod_time, last_mod_date),
|
||||
crc32: crc,
|
||||
compressed_size: compressed_size,
|
||||
uncompressed_size: uncompressed_size,
|
||||
file_name: file_name,
|
||||
extra_field: extra_field,
|
||||
file_comment: file_comment,
|
||||
disk_number: disk_number,
|
||||
file_offset: offset,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct DigitalSignature
|
||||
{
|
||||
data: Vec<u8>,
|
||||
}
|
||||
|
||||
impl DigitalSignature
|
||||
{
|
||||
pub fn parse<T: Reader>(reader: &mut T) -> IoResult<DigitalSignature>
|
||||
{
|
||||
let magic = try!(reader.read_le_u32());
|
||||
if magic != DIGITAL_SIGNATURE_SIGNATURE
|
||||
{
|
||||
return Err(IoError {
|
||||
kind: io::MismatchedFileTypeForOperation,
|
||||
desc: "Invalid digital signature header",
|
||||
detail: None })
|
||||
}
|
||||
let size = try!(reader.read_le_u16()) as uint;
|
||||
let data = try!(reader.read_exact(size));
|
||||
Ok(DigitalSignature { data: data })
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue