1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
pub const LOCAL_FILE_HEADER_SIGNATURE: u32 = 0x04034b50;
pub const DATA_DESCRIPTOR_SIGNATURE: u32 = 0x08074b50;
pub const CENTRAL_DIRECTORY_FILE_HEADER_SIGNATURE: u32 = 0x02014b50;
pub const END_OF_CENTRAL_DIRECTORY_RECORD_SIGNATURE: u32 = 0x06054b50;

#[repr(u16)]
pub enum VersionMadeBy {
    WindowsNTFS = 10,
}

#[repr(u16)]
pub enum CompressionMethod {
    Stored,
}

#[derive(Default)]
pub struct LocalFileEntry {
    pub header: LocalFileHeader,
    pub data: Vec<u8>,
}

impl LocalFileEntry {
    pub fn to_le_bytes(&self) -> Vec<u8> {
        let mut result = vec![];

        result.extend(self.header.to_le_bytes());
        result.extend(&self.data);

        result
    }
}

#[derive(Default)]
pub struct LocalFileHeader {
    pub signature: u32,
    pub extract_version: u16,
    pub gp_flag: u16,
    pub compression_method: u16,
    pub modified_time: u16,
    pub modified_date: u16,
    pub crc32: u32,
    pub compressed_size: u32,
    pub uncompressed_size: u32,
    pub file_name_len: u16,
    pub extra_field_len: u16,
    pub file_name: Vec<u8>,
    pub extra_field: Vec<u8>,
}

impl LocalFileHeader {
    pub fn to_le_bytes(&self) -> Vec<u8> {
        let mut result = vec![];

        result.extend(&self.signature.to_le_bytes());
        result.extend(&self.extract_version.to_le_bytes());
        result.extend(&self.gp_flag.to_le_bytes());
        result.extend(&self.compression_method.to_le_bytes());
        result.extend(&self.modified_time.to_le_bytes());
        result.extend(&self.modified_date.to_le_bytes());
        result.extend(&self.crc32.to_le_bytes());
        result.extend(&self.compressed_size.to_le_bytes());
        result.extend(&self.uncompressed_size.to_le_bytes());
        result.extend(&self.file_name_len.to_le_bytes());
        result.extend(&self.extra_field_len.to_le_bytes());
        result.extend(&self.file_name);
        result.extend(&self.extra_field);

        result
    }
}

#[derive(Default)]
pub struct CDFileHeader {
    pub signature: u32,
    pub version_made_by: u16,
    pub extract_version: u16,
    pub gp_flag: u16,
    pub compression_method: u16,
    pub modified_time: u16,
    pub modified_date: u16,
    pub crc32: u32,
    pub compressed_size: u32,
    pub uncompressed_size: u32,
    pub file_name_len: u16,
    pub extra_field_len: u16,
    pub comment_len: u16,
    pub start_disk_num: u16,
    pub internal_attributes: u16,
    pub external_attributes: u32,
    pub rel_offset: u32,
    pub file_name: Vec<u8>,
    pub extra_field: Vec<u8>,
    pub file_comment: Vec<u8>,
}
impl CDFileHeader {
    pub fn to_le_bytes(&self) -> Vec<u8> {
        let mut result = vec![];

        result.extend(&self.signature.to_le_bytes());
        result.extend(&self.version_made_by.to_le_bytes());
        result.extend(&self.extract_version.to_le_bytes());
        result.extend(&self.gp_flag.to_le_bytes());
        result.extend(&self.compression_method.to_le_bytes());
        result.extend(&self.modified_time.to_le_bytes());
        result.extend(&self.modified_date.to_le_bytes());
        result.extend(&self.crc32.to_le_bytes());
        result.extend(&self.compressed_size.to_le_bytes());
        result.extend(&self.uncompressed_size.to_le_bytes());
        result.extend(&self.file_name_len.to_le_bytes());
        result.extend(&self.extra_field_len.to_le_bytes());
        result.extend(&self.comment_len.to_le_bytes());
        result.extend(&self.start_disk_num.to_le_bytes());
        result.extend(&self.internal_attributes.to_le_bytes());
        result.extend(&self.external_attributes.to_le_bytes());
        result.extend(&self.rel_offset.to_le_bytes());
        result.extend(&self.file_name);
        result.extend(&self.extra_field);
        result.extend(&self.file_comment);

        result
    }
}

#[derive(Default)]
pub struct EndOfCD {
    pub signature: u32,
    pub disk_num: u16,
    pub start_disk: u16,
    pub total_records: u16,
    pub cd_size: u32,
    pub cd_offset: u32,
    pub comment_len: u16,
    pub comment: Vec<u8>,
}

impl EndOfCD {
    pub fn to_le_bytes(&self) -> Vec<u8> {
        let mut result = vec![];

        result.extend(&self.signature.to_le_bytes());
        result.extend(&self.disk_num.to_le_bytes());
        result.extend(&self.start_disk.to_le_bytes());
        result.extend(&self.total_records.to_le_bytes());
        result.extend(&self.cd_size.to_le_bytes());
        result.extend(&self.cd_offset.to_le_bytes());
        result.extend(&self.comment_len.to_le_bytes());
        result.extend(&self.comment);

        result
    }
}