transfer file from one zip to another, WIP

This commit is contained in:
Jean-Marie Mineau 2024-01-17 16:41:24 +01:00
parent 0fdf619360
commit 8157325a02
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
3 changed files with 86 additions and 14 deletions

View file

@ -14,6 +14,7 @@ use extra_fields::{ExtraField, Zip64ExtraField};
use file_header::FileHeader;
use local_file_header::LocalFileHeader;
pub use zip_reader::ZipFileReader;
pub use zip_writer::ZipFileWriter;
#[derive(Debug, Clone, PartialEq, Eq, Serializable, Default)]
pub struct Signature(pub u32);

View file

@ -1,12 +1,13 @@
use apk_frauder::ZipFileReader;
use apk_frauder::ZipFileWriter;
use std::fs::File;
fn main() {
/*
let file = File::open("app-release.apk").expect("failed to open file");
//let file = File::open("tst_64.zip").expect("failed to open file");
let zip_file = ZipFileReader::new(file);
//println!("{}", zip_file.get_file_names().join("\n"));
/*
for file in &zip_file.files {
println!("{}", file.get_name());
println!("local: {:?}", file.local_header.malformed_extra_field);
@ -33,6 +34,17 @@ fn main() {
println!("Not signed whith scheme >= v2");
}
zip_file.check_holes();
*/
println!("{:#?}", zip_file.get_file_info("classes.dex"));
*/
let file = File::open("app-release.apk").expect("failed to open file");
let out_file = File::create("app-release.out.zip").expect("failed to create file");
let mut zip_file = ZipFileReader::new(file);
let mut out_file =
ZipFileWriter::new(out_file, zip_file.zip64_end_of_central_directory.clone());
for f in zip_file.files.clone() {
out_file.insert_file_from_zip(f, &mut zip_file);
}
out_file.write_central_directory();
//println!("{:#?}", zip_file.zip64_end_of_central_directory);
}

View file

@ -1,9 +1,9 @@
use std::io::{Read, Seek, SeekFrom, Write};
use crate::{
end_of_central_directory::EndCentralDirectory,
end_of_central_directory::Zip64EndCentralDirectory, FileInfo, ZipFileReader,
use crate::end_of_central_directory::{
EndCentralDirectory, Zip64EndCentralDirectory, Zip64EndCentralDirectoryLocator,
};
use crate::{FileInfo, ZipFileReader};
use androscalpel_serializer::Serializable;
pub struct ZipFileWriter<T: Write> {
@ -14,6 +14,8 @@ pub struct ZipFileWriter<T: Write> {
}
impl<T: Write> ZipFileWriter<T> {
/// If provided, `zip64_info` is used to get the value that are not computable from
/// the state, like version needed to extract.
pub fn new(writer: T, zip64_info: Option<Zip64EndCentralDirectory>) -> Self {
Self {
current_offset: 0,
@ -53,18 +55,75 @@ impl<T: Write> ZipFileWriter<T> {
for file_info in &self.files {
file_info.header.serialize(&mut self.data).unwrap();
}
// TODO: zip64
let number_of_entries_in_central_directory_on_disk = self.files.len();
let number_of_entries_in_central_directory = self.files.len();
let size_central_directory: u64 = self
.files
.iter()
.map(|file| file.header.size() as u64)
.sum();
let offset_central_directory = self.current_offset;
let use_zip64 = (number_of_entries_in_central_directory_on_disk > u16::MAX as usize)
|| (number_of_entries_in_central_directory > u16::MAX as usize)
|| (size_central_directory > u32::MAX as u64)
|| (offset_central_directory > u32::MAX as u64)
|| self.zip64_end_of_central_directory.is_some();
if use_zip64 {
if self.zip64_end_of_central_directory.is_none() {
self.zip64_end_of_central_directory = Some(Zip64EndCentralDirectory {
version_made_by: 45,
version_needed_to_extract: 45,
number_of_this_disk: 0,
disk_number_of_central_directory_start: 0,
number_entry_in_central_directory_on_this_disk: 0,
number_entry_in_central_directory: 0,
size_of_central_directory: 0,
offset_central_directory: 0,
extensible_data: vec![],
})
}
let zip64_edc = self.zip64_end_of_central_directory.as_mut().unwrap();
zip64_edc.number_entry_in_central_directory_on_this_disk =
number_of_entries_in_central_directory_on_disk as u64;
zip64_edc.number_entry_in_central_directory =
number_of_entries_in_central_directory as u64;
zip64_edc.size_of_central_directory = size_central_directory;
zip64_edc.offset_central_directory = offset_central_directory;
zip64_edc.serialize(&mut self.data).unwrap();
Zip64EndCentralDirectoryLocator {
disk_number_of_zip64_end_central_directory_start: 0,
offset_zip64_end_of_central_directory_record: offset_central_directory
+ size_central_directory,
total_number_of_disks: 0,
}
.serialize(&mut self.data)
.unwrap();
}
EndCentralDirectory {
disk_number: 0,
disk_number_of_central_directory_start: 0,
number_of_entries_in_central_directory_on_disk: self.files.len() as u16,
number_of_entries_in_central_directory: self.files.len() as u16,
size_central_directory: self
.files
.iter()
.map(|file| file.local_header.size() as u32 + file.get_compressed_size() as u32)
.sum(),
offset_central_directory: self.current_offset as u32,
number_of_entries_in_central_directory_on_disk: if use_zip64 {
u16::MAX
} else {
number_of_entries_in_central_directory_on_disk as u16
},
number_of_entries_in_central_directory: if use_zip64 {
u16::MAX
} else {
number_of_entries_in_central_directory as u16
},
size_central_directory: if use_zip64 {
u32::MAX
} else {
size_central_directory as u32
},
offset_central_directory: if use_zip64 {
u32::MAX
} else {
offset_central_directory as u32
},
comment: vec![],
}
.serialize(&mut self.data)