Made finding of central directory possible
This commit is contained in:
parent
1cbc1e9e6a
commit
181993afd1
2 changed files with 78 additions and 10 deletions
17
src/bin/parse_foot.rs
Normal file
17
src/bin/parse_foot.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
extern crate zip;
|
||||||
|
|
||||||
|
fn main()
|
||||||
|
{
|
||||||
|
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::CentralDirectoryEnd::find_and_parse(&mut file).unwrap();
|
||||||
|
println!("{}", header);
|
||||||
|
|
||||||
|
file.seek(header.central_directory_offset as i64, std::io::SeekSet).unwrap();
|
||||||
|
for i in range(0, header.number_of_files_on_this_disk)
|
||||||
|
{
|
||||||
|
println!("{}", zip::spec::CentralDirectoryHeader::parse(&mut file).unwrap());
|
||||||
|
}
|
||||||
|
}
|
71
src/spec.rs
71
src/spec.rs
|
@ -1,12 +1,13 @@
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::{IoResult, IoError};
|
use std::io::{IoResult, IoError};
|
||||||
|
use std::iter::range_step_inclusive;
|
||||||
use time::Tm;
|
use time::Tm;
|
||||||
use util;
|
use util;
|
||||||
|
|
||||||
static LOCAL_FILE_HEADER_SIGNATURE : u32 = 0x04034b50;
|
static LOCAL_FILE_HEADER_SIGNATURE : u32 = 0x04034b50;
|
||||||
static DATA_DESCRIPTOR_SIGNATURE : u32 = 0x08074b50;
|
static DATA_DESCRIPTOR_SIGNATURE : u32 = 0x08074b50;
|
||||||
static CENTRAL_DIRECTORY_HEADER_SIGNATURE : u32 = 0x02014b50;
|
static CENTRAL_DIRECTORY_HEADER_SIGNATURE : u32 = 0x02014b50;
|
||||||
static DIGITAL_SIGNATURE_SIGNATURE : u32 = 0x05054b50;
|
static CENTRAL_DIRECTORY_END_SIGNATURE : u32 = 0x06054b50;
|
||||||
|
|
||||||
#[deriving(FromPrimitive, Show)]
|
#[deriving(FromPrimitive, Show)]
|
||||||
pub enum CompressionMethod
|
pub enum CompressionMethod
|
||||||
|
@ -139,7 +140,8 @@ impl DataDescriptor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CentralDirectoryHeader
|
#[deriving(Show)]
|
||||||
|
pub struct CentralDirectoryHeader
|
||||||
{
|
{
|
||||||
made_by: u16,
|
made_by: u16,
|
||||||
version_needed: u16,
|
version_needed: u16,
|
||||||
|
@ -226,25 +228,74 @@ impl CentralDirectoryHeader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DigitalSignature
|
#[deriving(Show)]
|
||||||
|
pub struct CentralDirectoryEnd
|
||||||
{
|
{
|
||||||
data: Vec<u8>,
|
number_of_disks: u16,
|
||||||
|
disk_with_central_directory: u16,
|
||||||
|
pub number_of_files_on_this_disk: u16,
|
||||||
|
number_of_files: u16,
|
||||||
|
central_directory_size: u32,
|
||||||
|
pub central_directory_offset: u32,
|
||||||
|
zip_file_comment: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DigitalSignature
|
impl CentralDirectoryEnd
|
||||||
{
|
{
|
||||||
pub fn parse<T: Reader>(reader: &mut T) -> IoResult<DigitalSignature>
|
pub fn parse<T: Reader>(reader: &mut T) -> IoResult<CentralDirectoryEnd>
|
||||||
{
|
{
|
||||||
let magic = try!(reader.read_le_u32());
|
let magic = try!(reader.read_le_u32());
|
||||||
if magic != DIGITAL_SIGNATURE_SIGNATURE
|
if magic != CENTRAL_DIRECTORY_END_SIGNATURE
|
||||||
{
|
{
|
||||||
return Err(IoError {
|
return Err(IoError {
|
||||||
kind: io::MismatchedFileTypeForOperation,
|
kind: io::MismatchedFileTypeForOperation,
|
||||||
desc: "Invalid digital signature header",
|
desc: "Invalid digital signature header",
|
||||||
detail: None })
|
detail: None })
|
||||||
}
|
}
|
||||||
let size = try!(reader.read_le_u16()) as uint;
|
let number_of_disks = try!(reader.read_le_u16());
|
||||||
let data = try!(reader.read_exact(size));
|
let disk_with_central_directory = try!(reader.read_le_u16());
|
||||||
Ok(DigitalSignature { data: data })
|
let number_of_files_on_this_disk = try!(reader.read_le_u16());
|
||||||
|
let number_of_files = try!(reader.read_le_u16());
|
||||||
|
let central_directory_size = try!(reader.read_le_u32());
|
||||||
|
let central_directory_offset = try!(reader.read_le_u32());
|
||||||
|
let zip_file_comment_length = try!(reader.read_le_u16()) as uint;
|
||||||
|
let zip_file_comment = try!(reader.read_exact(zip_file_comment_length));
|
||||||
|
|
||||||
|
Ok(CentralDirectoryEnd
|
||||||
|
{
|
||||||
|
number_of_disks: number_of_disks,
|
||||||
|
disk_with_central_directory: disk_with_central_directory,
|
||||||
|
number_of_files_on_this_disk: number_of_files_on_this_disk,
|
||||||
|
number_of_files: number_of_files,
|
||||||
|
central_directory_size: central_directory_size,
|
||||||
|
central_directory_offset: central_directory_offset,
|
||||||
|
zip_file_comment: zip_file_comment,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
pub fn find_and_parse<T: Reader+Seek>(reader: &mut T) -> IoResult<CentralDirectoryEnd>
|
||||||
|
{
|
||||||
|
let header_size = 22;
|
||||||
|
try!(reader.seek(0, io::SeekEnd));
|
||||||
|
let filelength = try!(reader.tell()) as i64;
|
||||||
|
for pos in range_step_inclusive(filelength - header_size, 0, -1)
|
||||||
|
{
|
||||||
|
try!(reader.seek(pos, io::SeekSet));
|
||||||
|
if try!(reader.read_le_u32()) == CENTRAL_DIRECTORY_END_SIGNATURE
|
||||||
|
{
|
||||||
|
try!(reader.seek(header_size - 6, io::SeekCur));
|
||||||
|
let comment_length = try!(reader.read_le_u16()) as i64;
|
||||||
|
if filelength - pos - header_size == comment_length
|
||||||
|
{
|
||||||
|
try!(reader.seek(pos, io::SeekSet));
|
||||||
|
return CentralDirectoryEnd::parse(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(IoError
|
||||||
|
{
|
||||||
|
kind: io::MismatchedFileTypeForOperation,
|
||||||
|
desc: "Could not find central directory end",
|
||||||
|
detail: None
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue