implement file insertion
This commit is contained in:
parent
7b6a5980c8
commit
0f5764c340
4 changed files with 98 additions and 17 deletions
|
|
@ -1,10 +1,9 @@
|
||||||
use std::io::{SeekFrom, Write};
|
use std::io::{SeekFrom, Write};
|
||||||
|
|
||||||
use crate::compression::CompressionMethod;
|
use crate::compression::CompressionMethod;
|
||||||
use crate::cp437::string_to_cp437;
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::extra_fields::{ExtraField, GenericExtraField, Zip64ExtraField};
|
use crate::extra_fields::{ExtraField, GenericExtraField, Zip64ExtraField};
|
||||||
use crate::{cp437, general_purpose_flags, Encoding, Signature};
|
use crate::{cp437, external_file_attributes, general_purpose_flags, Encoding, Signature};
|
||||||
use androscalpel_serializer::{ReadSeek, Result, Serializable};
|
use androscalpel_serializer::{ReadSeek, Result, Serializable};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
|
@ -191,18 +190,10 @@ impl FileHeader {
|
||||||
const MIN_SIZE: usize = 4 + 6 * 2 + 4 * 3 + 5 * 2 + 4 * 2;
|
const MIN_SIZE: usize = 4 + 6 * 2 + 4 * 3 + 5 * 2 + 4 * 2;
|
||||||
|
|
||||||
pub fn new_default(name: &str) -> Self {
|
pub fn new_default(name: &str) -> Self {
|
||||||
let mut general_purpose_flags = 0;
|
let mut header = FileHeader {
|
||||||
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_made_by: 768,
|
||||||
version_needed_to_extract: 0,
|
version_needed_to_extract: 0,
|
||||||
general_purpose_flags,
|
general_purpose_flags: 0,
|
||||||
compression_method: CompressionMethod::Deflated,
|
compression_method: CompressionMethod::Deflated,
|
||||||
last_mod_file_time: 0,
|
last_mod_file_time: 0,
|
||||||
last_mod_file_data: 0,
|
last_mod_file_data: 0,
|
||||||
|
|
@ -211,13 +202,20 @@ impl FileHeader {
|
||||||
uncompressed_size: 0,
|
uncompressed_size: 0,
|
||||||
disk_number_start: 0,
|
disk_number_start: 0,
|
||||||
internal_file_attributes: 0,
|
internal_file_attributes: 0,
|
||||||
external_file_attributes: 0b1000000110100100 << 16, // TODO
|
// TODO: why 0b10000000 ?
|
||||||
|
external_file_attributes: external_file_attributes::REGULAR_FILE
|
||||||
|
| external_file_attributes::PERM_UR
|
||||||
|
| external_file_attributes::PERM_UW
|
||||||
|
| external_file_attributes::PERM_GR
|
||||||
|
| external_file_attributes::PERM_OR, // TODO
|
||||||
offset_local_header: 0,
|
offset_local_header: 0,
|
||||||
file_name,
|
file_name: vec![],
|
||||||
extra_field: vec![],
|
extra_field: vec![],
|
||||||
malformed_extra_field: vec![],
|
malformed_extra_field: vec![],
|
||||||
file_comment: vec![],
|
file_comment: vec![],
|
||||||
}
|
};
|
||||||
|
header.set_name(name);
|
||||||
|
header
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_name_encoding(&self) -> Encoding {
|
pub fn get_name_encoding(&self) -> Encoding {
|
||||||
|
|
@ -227,13 +225,36 @@ impl FileHeader {
|
||||||
Encoding::CP437
|
Encoding::CP437
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_name(&self) -> String {
|
pub fn get_name(&self) -> String {
|
||||||
match self.get_name_encoding() {
|
match self.get_name_encoding() {
|
||||||
Encoding::UTF8 => std::str::from_utf8(&self.file_name).unwrap().into(),
|
Encoding::UTF8 => std::str::from_utf8(&self.file_name).unwrap().into(),
|
||||||
Encoding::CP437 => cp437::cp437_to_string(&self.file_name),
|
Encoding::CP437 => cp437::cp437_to_string(&self.file_name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn external_file_attributes_set_flag(&mut self, flag: u32) {
|
||||||
|
self.external_file_attributes |= flag;
|
||||||
|
}
|
||||||
|
pub fn external_file_attributes_unset_flag(&mut self, flag: u32) {
|
||||||
|
self.external_file_attributes &= !flag;
|
||||||
|
}
|
||||||
|
pub fn set_file_type(&mut self, file_type: u32) {
|
||||||
|
self.external_file_attributes &= !external_file_attributes::MASK_FILE_TYPE;
|
||||||
|
self.external_file_attributes |= file_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_name(&mut self, name: &str) {
|
||||||
|
let file_name = match cp437::string_to_cp437(name) {
|
||||||
|
Ok(name) => {
|
||||||
|
self.general_purpose_flags &= !general_purpose_flags::MASK_UTF8_FILENAME;
|
||||||
|
name
|
||||||
|
}
|
||||||
|
Err(Error::NotCp437) => {
|
||||||
|
self.general_purpose_flags |= general_purpose_flags::MASK_UTF8_FILENAME;
|
||||||
|
name.as_bytes().into()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self.file_name = file_name;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_uncompressed_size(&self) -> u64 {
|
pub fn get_uncompressed_size(&self) -> u64 {
|
||||||
if self.uncompressed_size != u32::MAX {
|
if self.uncompressed_size != u32::MAX {
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,29 @@ pub mod general_purpose_flags {
|
||||||
pub const MASK_ENCRYPTED_CENTRAL_DIR: u16 = 1 << 13;
|
pub const MASK_ENCRYPTED_CENTRAL_DIR: u16 = 1 << 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod external_file_attributes {
|
||||||
|
pub const FIFO_FILE: u32 = 0b00010000 << 24;
|
||||||
|
// #define S_IFCHR 0020000 /* character special */ ?
|
||||||
|
pub const DIR_FILE: u32 = 0b01000000 << 24;
|
||||||
|
// #define S_IFBLK 0060000 /* block special */ ?
|
||||||
|
pub const SYMBOLIC_LINK_FILE: u32 = 0b10100000 << 24;
|
||||||
|
pub const SOCKET_FILE: u32 = 0b11000000 << 24;
|
||||||
|
pub const REGULAR_FILE: u32 = 0b10000000 << 24;
|
||||||
|
pub const MASK_FILE_TYPE: u32 = 0b11110000 << 24;
|
||||||
|
pub const SETUID: u32 = 0b0000100000000000 << 16;
|
||||||
|
pub const SETGID: u32 = 0b0000010000000000 << 16;
|
||||||
|
pub const STICKY: u32 = 0b0000001000000000 << 16;
|
||||||
|
pub const PERM_UR: u32 = 0b0000000100000000 << 16;
|
||||||
|
pub const PERM_UW: u32 = 0b0000000010000000 << 16;
|
||||||
|
pub const PERM_UX: u32 = 0b0000000001000000 << 16;
|
||||||
|
pub const PERM_GR: u32 = 0b0000000000100000 << 16;
|
||||||
|
pub const PERM_GW: u32 = 0b0000000000010000 << 16;
|
||||||
|
pub const PERM_GX: u32 = 0b0000000000001000 << 16;
|
||||||
|
pub const PERM_OR: u32 = 0b0000000000000100 << 16;
|
||||||
|
pub const PERM_OW: u32 = 0b0000000000000010 << 16;
|
||||||
|
pub const PERM_OX: u32 = 0b0000000000000001 << 16;
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct FileInfo {
|
pub struct FileInfo {
|
||||||
pub local_header: LocalFileHeader,
|
pub local_header: LocalFileHeader,
|
||||||
|
|
@ -46,6 +69,19 @@ impl FileInfo {
|
||||||
pub fn get_name(&self) -> String {
|
pub fn get_name(&self) -> String {
|
||||||
self.header.get_name()
|
self.header.get_name()
|
||||||
}
|
}
|
||||||
|
pub fn set_name(&mut self, name: &str) {
|
||||||
|
self.header.set_name(name);
|
||||||
|
self.local_header.set_name(name);
|
||||||
|
}
|
||||||
|
pub fn external_file_attributes_set_flag(&mut self, flag: u32) {
|
||||||
|
self.header.external_file_attributes_set_flag(flag);
|
||||||
|
}
|
||||||
|
pub fn external_file_attributes_unset_flag(&mut self, flag: u32) {
|
||||||
|
self.header.external_file_attributes_unset_flag(flag);
|
||||||
|
}
|
||||||
|
pub fn set_file_type(&mut self, file_type: u32) {
|
||||||
|
self.header.set_file_type(file_type);
|
||||||
|
}
|
||||||
pub fn get_offset_local_header(&self) -> u64 {
|
pub fn get_offset_local_header(&self) -> u64 {
|
||||||
self.header.get_offset_local_header()
|
self.header.get_offset_local_header()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use std::io::{SeekFrom, Write};
|
use std::io::{SeekFrom, Write};
|
||||||
|
|
||||||
use crate::compression::CompressionMethod;
|
use crate::compression::CompressionMethod;
|
||||||
|
use crate::error::Error;
|
||||||
use crate::extra_fields::{ExtraField, GenericExtraField, Zip64ExtraField};
|
use crate::extra_fields::{ExtraField, GenericExtraField, Zip64ExtraField};
|
||||||
use crate::{cp437, general_purpose_flags, Encoding, Signature};
|
use crate::{cp437, general_purpose_flags, Encoding, Signature};
|
||||||
use androscalpel_serializer::{ReadSeek, Result, Serializable};
|
use androscalpel_serializer::{ReadSeek, Result, Serializable};
|
||||||
|
|
@ -198,6 +199,20 @@ impl LocalFileHeader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_name(&mut self, name: &str) {
|
||||||
|
let file_name = match cp437::string_to_cp437(name) {
|
||||||
|
Ok(name) => {
|
||||||
|
self.general_purpose_flags &= !general_purpose_flags::MASK_UTF8_FILENAME;
|
||||||
|
name
|
||||||
|
}
|
||||||
|
Err(Error::NotCp437) => {
|
||||||
|
self.general_purpose_flags |= general_purpose_flags::MASK_UTF8_FILENAME;
|
||||||
|
name.as_bytes().into()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self.file_name = file_name;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_uncompressed_size(&self) -> u64 {
|
pub fn get_uncompressed_size(&self) -> u64 {
|
||||||
if self.uncompressed_size != u32::MAX {
|
if self.uncompressed_size != u32::MAX {
|
||||||
self.uncompressed_size as u64
|
self.uncompressed_size as u64
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use apk_frauder::external_file_attributes;
|
||||||
use apk_frauder::file_header::FileHeader;
|
use apk_frauder::file_header::FileHeader;
|
||||||
use apk_frauder::ZipFileReader;
|
use apk_frauder::ZipFileReader;
|
||||||
use apk_frauder::ZipFileWriter;
|
use apk_frauder::ZipFileWriter;
|
||||||
|
|
@ -59,9 +60,17 @@ fn main() {
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
out_file.insert_file(
|
out_file.insert_file(
|
||||||
&mut Cursor::new(b"Hello World\n"),
|
&mut Cursor::new(b"Hello World !!!\n"),
|
||||||
FileHeader::new_default("plip.txt"),
|
FileHeader::new_default("plip.txt"),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//let mut header_dir = FileHeader::new_default("dir");
|
||||||
|
//header_dir.set_file_type(external_file_attributes::DIR_FILE);
|
||||||
|
//out_file.insert_file(&mut Cursor::new(b""), header_dir, None);
|
||||||
|
let mut header_link = FileHeader::new_default("dir/link");
|
||||||
|
header_link.set_file_type(external_file_attributes::SYMBOLIC_LINK_FILE);
|
||||||
|
out_file.insert_file(&mut Cursor::new(b"../plop.txt"), header_link, None);
|
||||||
|
|
||||||
out_file.write_central_directory();
|
out_file.write_central_directory();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue