insert file in zip
This commit is contained in:
parent
3f521b5754
commit
7b6a5980c8
6 changed files with 210 additions and 8 deletions
|
|
@ -1,4 +1,5 @@
|
|||
/// Convert cp437 encoded string to [`String`].
|
||||
use crate::error::Error;
|
||||
|
||||
pub fn cp437_char_to_char(input: u8) -> char {
|
||||
char::from_u32(match input {
|
||||
|
|
@ -138,3 +139,147 @@ pub fn cp437_char_to_char(input: u8) -> char {
|
|||
pub fn cp437_to_string(input: &[u8]) -> String {
|
||||
input.iter().cloned().map(cp437_char_to_char).collect()
|
||||
}
|
||||
|
||||
pub fn char_to_cp437_char(input: char) -> Result<u8, Error> {
|
||||
let input: u32 = input.into();
|
||||
match input {
|
||||
0x00..=0x7f => Ok(input as u8),
|
||||
0x00c7 => Ok(0x80),
|
||||
0x00fc => Ok(0x81),
|
||||
0x00e9 => Ok(0x82),
|
||||
0x00e2 => Ok(0x83),
|
||||
0x00e4 => Ok(0x84),
|
||||
0x00e0 => Ok(0x85),
|
||||
0x00e5 => Ok(0x86),
|
||||
0x00e7 => Ok(0x87),
|
||||
0x00ea => Ok(0x88),
|
||||
0x00eb => Ok(0x89),
|
||||
0x00e8 => Ok(0x8a),
|
||||
0x00ef => Ok(0x8b),
|
||||
0x00ee => Ok(0x8c),
|
||||
0x00ec => Ok(0x8d),
|
||||
0x00c4 => Ok(0x8e),
|
||||
0x00c5 => Ok(0x8f),
|
||||
0x00c9 => Ok(0x90),
|
||||
0x00e6 => Ok(0x91),
|
||||
0x00c6 => Ok(0x92),
|
||||
0x00f4 => Ok(0x93),
|
||||
0x00f6 => Ok(0x94),
|
||||
0x00f2 => Ok(0x95),
|
||||
0x00fb => Ok(0x96),
|
||||
0x00f9 => Ok(0x97),
|
||||
0x00ff => Ok(0x98),
|
||||
0x00d6 => Ok(0x99),
|
||||
0x00dc => Ok(0x9a),
|
||||
0x00a2 => Ok(0x9b),
|
||||
0x00a3 => Ok(0x9c),
|
||||
0x00a5 => Ok(0x9d),
|
||||
0x20a7 => Ok(0x9e),
|
||||
0x0192 => Ok(0x9f),
|
||||
0x00e1 => Ok(0xa0),
|
||||
0x00ed => Ok(0xa1),
|
||||
0x00f3 => Ok(0xa2),
|
||||
0x00fa => Ok(0xa3),
|
||||
0x00f1 => Ok(0xa4),
|
||||
0x00d1 => Ok(0xa5),
|
||||
0x00aa => Ok(0xa6),
|
||||
0x00ba => Ok(0xa7),
|
||||
0x00bf => Ok(0xa8),
|
||||
0x2310 => Ok(0xa9),
|
||||
0x00ac => Ok(0xaa),
|
||||
0x00bd => Ok(0xab),
|
||||
0x00bc => Ok(0xac),
|
||||
0x00a1 => Ok(0xad),
|
||||
0x00ab => Ok(0xae),
|
||||
0x00bb => Ok(0xaf),
|
||||
0x2591 => Ok(0xb0),
|
||||
0x2592 => Ok(0xb1),
|
||||
0x2593 => Ok(0xb2),
|
||||
0x2502 => Ok(0xb3),
|
||||
0x2524 => Ok(0xb4),
|
||||
0x2561 => Ok(0xb5),
|
||||
0x2562 => Ok(0xb6),
|
||||
0x2556 => Ok(0xb7),
|
||||
0x2555 => Ok(0xb8),
|
||||
0x2563 => Ok(0xb9),
|
||||
0x2551 => Ok(0xba),
|
||||
0x2557 => Ok(0xbb),
|
||||
0x255d => Ok(0xbc),
|
||||
0x255c => Ok(0xbd),
|
||||
0x255b => Ok(0xbe),
|
||||
0x2510 => Ok(0xbf),
|
||||
0x2514 => Ok(0xc0),
|
||||
0x2534 => Ok(0xc1),
|
||||
0x252c => Ok(0xc2),
|
||||
0x251c => Ok(0xc3),
|
||||
0x2500 => Ok(0xc4),
|
||||
0x253c => Ok(0xc5),
|
||||
0x255e => Ok(0xc6),
|
||||
0x255f => Ok(0xc7),
|
||||
0x255a => Ok(0xc8),
|
||||
0x2554 => Ok(0xc9),
|
||||
0x2569 => Ok(0xca),
|
||||
0x2566 => Ok(0xcb),
|
||||
0x2560 => Ok(0xcc),
|
||||
0x2550 => Ok(0xcd),
|
||||
0x256c => Ok(0xce),
|
||||
0x2567 => Ok(0xcf),
|
||||
0x2568 => Ok(0xd0),
|
||||
0x2564 => Ok(0xd1),
|
||||
0x2565 => Ok(0xd2),
|
||||
0x2559 => Ok(0xd3),
|
||||
0x2558 => Ok(0xd4),
|
||||
0x2552 => Ok(0xd5),
|
||||
0x2553 => Ok(0xd6),
|
||||
0x256b => Ok(0xd7),
|
||||
0x256a => Ok(0xd8),
|
||||
0x2518 => Ok(0xd9),
|
||||
0x250c => Ok(0xda),
|
||||
0x2588 => Ok(0xdb),
|
||||
0x2584 => Ok(0xdc),
|
||||
0x258c => Ok(0xdd),
|
||||
0x2590 => Ok(0xde),
|
||||
0x2580 => Ok(0xdf),
|
||||
0x03b1 => Ok(0xe0),
|
||||
0x00df => Ok(0xe1),
|
||||
0x0393 => Ok(0xe2),
|
||||
0x03c0 => Ok(0xe3),
|
||||
0x03a3 => Ok(0xe4),
|
||||
0x03c3 => Ok(0xe5),
|
||||
0x00b5 => Ok(0xe6),
|
||||
0x03c4 => Ok(0xe7),
|
||||
0x03a6 => Ok(0xe8),
|
||||
0x0398 => Ok(0xe9),
|
||||
0x03a9 => Ok(0xea),
|
||||
0x03b4 => Ok(0xeb),
|
||||
0x221e => Ok(0xec),
|
||||
0x03c6 => Ok(0xed),
|
||||
0x03b5 => Ok(0xee),
|
||||
0x2229 => Ok(0xef),
|
||||
0x2261 => Ok(0xf0),
|
||||
0x00b1 => Ok(0xf1),
|
||||
0x2265 => Ok(0xf2),
|
||||
0x2264 => Ok(0xf3),
|
||||
0x2320 => Ok(0xf4),
|
||||
0x2321 => Ok(0xf5),
|
||||
0x00f7 => Ok(0xf6),
|
||||
0x2248 => Ok(0xf7),
|
||||
0x00b0 => Ok(0xf8),
|
||||
0x2219 => Ok(0xf9),
|
||||
0x00b7 => Ok(0xfa),
|
||||
0x221a => Ok(0xfb),
|
||||
0x207f => Ok(0xfc),
|
||||
0x00b2 => Ok(0xfd),
|
||||
0x25a0 => Ok(0xfe),
|
||||
0x00a0 => Ok(0xff),
|
||||
_ => Err(Error::NotCp437),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn string_to_cp437(input: &str) -> Result<Vec<u8>, Error> {
|
||||
let mut bin = vec![];
|
||||
for cha in input.chars() {
|
||||
bin.push(char_to_cp437_char(cha)?);
|
||||
}
|
||||
Ok(bin)
|
||||
}
|
||||
|
|
|
|||
4
apk_frauder/src/error.rs
Normal file
4
apk_frauder/src/error.rs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum Error {
|
||||
NotCp437,
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
use std::io::{SeekFrom, Write};
|
||||
|
||||
use crate::compression::CompressionMethod;
|
||||
use crate::cp437::string_to_cp437;
|
||||
use crate::error::Error;
|
||||
use crate::extra_fields::{ExtraField, GenericExtraField, Zip64ExtraField};
|
||||
use crate::{cp437, general_purpose_flags, Encoding, Signature};
|
||||
use androscalpel_serializer::{ReadSeek, Result, Serializable};
|
||||
|
|
@ -188,6 +190,36 @@ impl FileHeader {
|
|||
const SIGNATURE: Signature = Signature(0x02014b50);
|
||||
const MIN_SIZE: usize = 4 + 6 * 2 + 4 * 3 + 5 * 2 + 4 * 2;
|
||||
|
||||
pub fn new_default(name: &str) -> Self {
|
||||
let mut general_purpose_flags = 0;
|
||||
let file_name = match string_to_cp437(name) {
|
||||
Ok(name) => name,
|
||||
Err(Error::NotCp437) => {
|
||||
general_purpose_flags |= general_purpose_flags::MASK_UTF8_FILENAME;
|
||||
name.as_bytes().into()
|
||||
}
|
||||
};
|
||||
FileHeader {
|
||||
version_made_by: 768,
|
||||
version_needed_to_extract: 0,
|
||||
general_purpose_flags,
|
||||
compression_method: CompressionMethod::Deflated,
|
||||
last_mod_file_time: 0,
|
||||
last_mod_file_data: 0,
|
||||
crc_32: 0,
|
||||
compressed_size: 0,
|
||||
uncompressed_size: 0,
|
||||
disk_number_start: 0,
|
||||
internal_file_attributes: 0,
|
||||
external_file_attributes: 0b1000000110100100 << 16, // TODO
|
||||
offset_local_header: 0,
|
||||
file_name,
|
||||
extra_field: vec![],
|
||||
malformed_extra_field: vec![],
|
||||
file_comment: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_name_encoding(&self) -> Encoding {
|
||||
if self.general_purpose_flags & general_purpose_flags::MASK_UTF8_FILENAME != 0 {
|
||||
Encoding::UTF8
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ pub mod apk_signing_block;
|
|||
pub mod compression;
|
||||
mod cp437;
|
||||
pub mod end_of_central_directory;
|
||||
pub mod error;
|
||||
pub mod extra_fields;
|
||||
pub mod file_header;
|
||||
pub mod local_file_header;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
use apk_frauder::file_header::FileHeader;
|
||||
use apk_frauder::ZipFileReader;
|
||||
use apk_frauder::ZipFileWriter;
|
||||
use std::fs::File;
|
||||
use std::io::Cursor;
|
||||
|
||||
fn main() {
|
||||
let file = File::open("app-release.apk").expect("failed to open file");
|
||||
//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);
|
||||
//let zip_file = ZipFileReader::new(file);
|
||||
/*
|
||||
//println!("{}", zip_file.get_file_names().join("\n"));
|
||||
for file in &zip_file.files {
|
||||
|
|
@ -35,7 +37,7 @@ fn main() {
|
|||
}
|
||||
zip_file.check_holes();
|
||||
*/
|
||||
println!("{:#?}", zip_file.get_file_info("classes.dex"));
|
||||
//println!("{:#?}", zip_file.get_file_info("classes.dex"));
|
||||
|
||||
/*
|
||||
let file = File::open("tst_64.zip").expect("failed to open file");
|
||||
|
|
@ -49,4 +51,17 @@ fn main() {
|
|||
out_file.write_central_directory();
|
||||
*/
|
||||
//println!("{:#?}", zip_file.zip64_end_of_central_directory);
|
||||
let out_file = File::create("test_write.zip").expect("failed to create file");
|
||||
let mut out_file = ZipFileWriter::new(out_file, None);
|
||||
out_file.insert_file(
|
||||
&mut Cursor::new(b"plop\n"),
|
||||
FileHeader::new_default("plop.txt"),
|
||||
None,
|
||||
);
|
||||
out_file.insert_file(
|
||||
&mut Cursor::new(b"Hello World\n"),
|
||||
FileHeader::new_default("plip.txt"),
|
||||
None,
|
||||
);
|
||||
out_file.write_central_directory();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -166,13 +166,12 @@ impl<T: Write> ZipFileWriter<T> {
|
|||
CompressionMethod::Deflated => {
|
||||
// TODO: find a way to do this in place, the compressed data can be large, and storing it
|
||||
// in memory is bad, but Deflate consume the Reader, so we cannot juste give it self.data
|
||||
// TODO: Compression::default -> nop, use flags
|
||||
// TODO: Compression::default -> use flag?
|
||||
let mut compressor =
|
||||
DeflateEncoder::new(CrcWriter::new(Vec::new()), Compression::default());
|
||||
CrcWriter::new(DeflateEncoder::new(Vec::new(), Compression::default()));
|
||||
io::copy(file, &mut compressor).unwrap();
|
||||
let finished = compressor.finish().unwrap();
|
||||
local_header.crc_32 = finished.crc().sum();
|
||||
finished.into_inner()
|
||||
local_header.crc_32 = compressor.crc().sum();
|
||||
compressor.into_inner().finish().unwrap()
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
|
|
@ -187,6 +186,12 @@ impl<T: Write> ZipFileWriter<T> {
|
|||
header.set_uncompressed_size(local_header.get_uncompressed_size());
|
||||
header.set_offset_local_header(header_offset);
|
||||
|
||||
// TODO: compression flags are not used right now, set to zero
|
||||
local_header.general_purpose_flags &= !(general_purpose_flags::MASK_COMPRESS_OPTION_1
|
||||
| general_purpose_flags::MASK_COMPRESS_OPTION_2);
|
||||
header.general_purpose_flags &= !(general_purpose_flags::MASK_COMPRESS_OPTION_1
|
||||
| general_purpose_flags::MASK_COMPRESS_OPTION_2);
|
||||
|
||||
let file_info = FileInfo {
|
||||
local_header,
|
||||
header,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue