1#![allow(unused)]
2use crate::{folder::*, method_options::MethodOptions};
3use bit_set::BitSet;
4use nt_time::FileTime;
5use std::{any::Any, collections::LinkedList, sync::Arc, time::SystemTime};
6
7pub(crate) const SIGNATURE_HEADER_SIZE: u64 = 32;
8pub(crate) const SEVEN_Z_SIGNATURE: &[u8] = &[b'7', b'z', 0xBC, 0xAF, 0x27, 0x1C];
9
10pub(crate) const K_END: u8 = 0x00;
11pub(crate) const K_HEADER: u8 = 0x01;
12pub(crate) const K_ARCHIVE_PROPERTIES: u8 = 0x02;
13pub(crate) const K_ADDITIONAL_STREAMS_INFO: u8 = 0x03;
14pub(crate) const K_MAIN_STREAMS_INFO: u8 = 0x04;
15pub(crate) const K_FILES_INFO: u8 = 0x05;
16pub(crate) const K_PACK_INFO: u8 = 0x06;
17pub(crate) const K_UNPACK_INFO: u8 = 0x07;
18pub(crate) const K_SUB_STREAMS_INFO: u8 = 0x08;
19pub(crate) const K_SIZE: u8 = 0x09;
20pub(crate) const K_CRC: u8 = 0x0A;
21pub(crate) const K_FOLDER: u8 = 0x0B;
22pub(crate) const K_CODERS_UNPACK_SIZE: u8 = 0x0C;
23pub(crate) const K_NUM_UNPACK_STREAM: u8 = 0x0D;
24pub(crate) const K_EMPTY_STREAM: u8 = 0x0E;
25pub(crate) const K_EMPTY_FILE: u8 = 0x0F;
26pub(crate) const K_ANTI: u8 = 0x10;
27pub(crate) const K_NAME: u8 = 0x11;
28pub(crate) const K_C_TIME: u8 = 0x12;
29pub(crate) const K_A_TIME: u8 = 0x13;
30pub(crate) const K_M_TIME: u8 = 0x14;
31pub(crate) const K_WIN_ATTRIBUTES: u8 = 0x15;
32pub(crate) const K_COMMENT: u8 = 0x16;
33pub(crate) const K_ENCODED_HEADER: u8 = 0x17;
34pub(crate) const K_START_POS: u8 = 0x18;
35pub(crate) const K_DUMMY: u8 = 0x19;
36
37#[derive(Debug, Default, Clone)]
38pub struct Archive {
39 pub pack_pos: u64,
41 pub pack_sizes: Vec<u64>,
42 pub pack_crcs_defined: bit_set::BitSet,
43 pub pack_crcs: Vec<u64>,
44 pub folders: Vec<Folder>,
45 pub sub_streams_info: Option<SubStreamsInfo>,
46 pub files: Vec<SevenZArchiveEntry>,
47 pub stream_map: StreamMap,
48}
49
50#[derive(Debug, Default, Clone)]
51pub struct SubStreamsInfo {
52 pub unpack_sizes: Vec<u64>,
53 pub has_crc: BitSet,
54 pub crcs: Vec<u64>,
55}
56
57#[derive(Debug, Default, Clone)]
58pub struct SevenZArchiveEntry {
59 pub name: String,
60 pub has_stream: bool,
61 pub is_directory: bool,
62 pub is_anti_item: bool,
63 pub has_creation_date: bool,
64 pub has_last_modified_date: bool,
65 pub has_access_date: bool,
66 pub creation_date: FileTime,
67 pub last_modified_date: FileTime,
68 pub access_date: FileTime,
69 pub has_windows_attributes: bool,
70 pub windows_attributes: u32,
71 pub has_crc: bool,
72 pub crc: u64,
73 pub compressed_crc: u64,
74 pub size: u64,
75 pub compressed_size: u64,
76 pub(crate) content_methods: Arc<Vec<SevenZMethodConfiguration>>,
78}
79
80impl SevenZArchiveEntry {
81 pub fn new() -> Self {
82 Default::default()
83 }
84
85 pub fn name(&self) -> &str {
86 self.name.as_ref()
87 }
88
89 pub fn is_directory(&self) -> bool {
90 self.is_directory
91 }
92
93 pub fn has_stream(&self) -> bool {
94 self.has_stream
95 }
96
97 pub fn creation_date(&self) -> FileTime {
98 self.creation_date
99 }
100
101 pub fn last_modified_date(&self) -> FileTime {
102 self.last_modified_date
103 }
104
105 pub fn size(&self) -> u64 {
106 self.size
107 }
108
109 pub fn windows_attributes(&self) -> u32 {
110 self.windows_attributes
111 }
112
113 pub fn access_date(&self) -> FileTime {
114 self.access_date
115 }
116
117 pub fn is_anti_item(&self) -> bool {
118 self.is_anti_item
119 }
120
121 pub fn from_path(path: impl AsRef<std::path::Path>, entry_name: String) -> SevenZArchiveEntry {
122 let path = path.as_ref();
123 #[cfg(target_os = "windows")]
124 let entry_name = {
125 let mut name_bytes = entry_name.into_bytes();
126 for b in &mut name_bytes {
127 if *b == b'\\' {
128 *b = b'/';
129 }
130 }
131 String::from_utf8(name_bytes).unwrap()
132 };
133 let mut entry = SevenZArchiveEntry {
134 name: entry_name,
135 has_stream: path.is_file(),
136 is_directory: path.is_dir(),
137 ..Default::default()
138 };
139
140 if let Ok(meta) = path.metadata() {
141 if let Ok(modified) = meta.modified() {
142 if let Ok(date) = modified.try_into() {
143 entry.last_modified_date = date;
144 entry.has_last_modified_date = entry.last_modified_date.to_raw() > 0;
145 }
146 }
147 if let Ok(date) = meta.created() {
148 if let Ok(date) = date.try_into() {
149 entry.creation_date = date;
150 entry.has_creation_date = entry.creation_date.to_raw() > 0;
151 }
152 }
153 if let Ok(date) = meta.accessed() {
154 if let Ok(date) = date.try_into() {
155 entry.access_date = date;
156 entry.has_access_date = entry.access_date.to_raw() > 0;
157 }
158 }
159 }
160 entry
161 }
162}
163
164#[derive(Debug, Default)]
165pub struct SevenZMethodConfiguration {
166 pub method: SevenZMethod,
167 pub options: Option<MethodOptions>,
168}
169
170impl From<SevenZMethod> for SevenZMethodConfiguration {
171 fn from(value: SevenZMethod) -> Self {
172 Self::new(value)
173 }
174}
175
176impl Clone for SevenZMethodConfiguration {
177 fn clone(&self) -> Self {
178 Self {
179 method: self.method,
180 options: self.options.clone(),
181 }
182 }
183}
184
185impl SevenZMethodConfiguration {
186 pub fn new(method: SevenZMethod) -> Self {
187 Self {
188 method,
189 options: None,
190 }
191 }
192
193 pub fn with_options(mut self, options: MethodOptions) -> Self {
194 self.options = Some(options);
195 self
196 }
197}
198
199#[derive(Debug, Clone, Copy, Eq, PartialEq, Default, Hash)]
200pub struct SevenZMethod(&'static str, &'static [u8]);
201
202impl SevenZMethod {
203 pub const ID_COPY: &'static [u8] = &[0x00];
204
205 pub const ID_LZMA: &'static [u8] = &[0x03, 0x01, 0x01];
206 pub const ID_LZMA2: &'static [u8] = &[0x21];
207 pub const ID_ZSTD: &'static [u8] = &[4, 247, 17, 1];
208 pub const ID_DEFLATE: &'static [u8] = &[0x04, 0x01, 0x08];
209 pub const ID_DEFLATE64: &'static [u8] = &[0x04, 0x01, 0x09];
210
211 pub const ID_BCJ_X86: &'static [u8] = &[0x03, 0x03, 0x01, 0x03];
212 pub const ID_BCJ_PPC: &'static [u8] = &[0x03, 0x03, 0x02, 0x05];
213 pub const ID_BCJ_IA64: &'static [u8] = &[0x03, 0x03, 0x04, 0x01];
214 pub const ID_BCJ_ARM: &'static [u8] = &[0x03, 0x03, 0x05, 0x01];
215 pub const ID_BCJ_ARM_THUMB: &'static [u8] = &[0x03, 0x03, 0x07, 0x01];
216 pub const ID_BCJ_SPARC: &'static [u8] = &[0x03, 0x03, 0x08, 0x05];
217 pub const ID_DELTA: &'static [u8] = &[0x03];
218 pub const ID_BZIP2: &'static [u8] = &[0x04, 0x02, 0x02];
219 pub const ID_AES256SHA256: &'static [u8] = &[0x06, 0xf1, 0x07, 0x01];
220 pub const ID_BCJ2: &'static [u8] = &[0x03, 0x03, 0x01, 0x1B];
221 pub const COPY: SevenZMethod = Self("COPY", Self::ID_COPY);
223
224 pub const LZMA: Self = Self("LZMA", Self::ID_LZMA);
225 pub const LZMA2: Self = Self("LZMA2", Self::ID_LZMA2);
226 pub const ZSTD: Self = Self("ZSTD", Self::ID_ZSTD);
227
228 pub const DEFLATE: Self = Self("DEFLATE", Self::ID_DEFLATE);
229 pub const DEFLATE64: Self = Self("DEFLATE64", Self::ID_DEFLATE64);
230
231 pub const BZIP2: Self = Self("BZIP2", Self::ID_BZIP2);
232 pub const AES256SHA256: Self = Self("AES256SHA256", Self::ID_AES256SHA256);
233
234 pub const BCJ_X86_FILTER: Self = Self("BCJ_X86", Self::ID_BCJ_X86);
235 pub const BCJ_PPC_FILTER: Self = Self("BCJ_PPC", Self::ID_BCJ_PPC);
236 pub const BCJ_IA64_FILTER: Self = Self("BCJ_IA64", Self::ID_BCJ_IA64);
237 pub const BCJ_ARM_FILTER: Self = Self("BCJ_ARM", Self::ID_BCJ_ARM);
238 pub const BCJ_ARM_THUMB_FILTER: Self = Self("BCJ_ARM_THUMB", Self::ID_BCJ_ARM_THUMB);
239 pub const BCJ_SPARC_FILTER: Self = Self("BCJ_SPARC", Self::ID_BCJ_SPARC);
240 pub const DELTA_FILTER: Self = Self("DELTA", Self::ID_DELTA);
241 pub const BCJ2_FILTER: Self = Self("BCJ2", Self::ID_BCJ2);
242
243 const METHODS: &'static [&'static SevenZMethod] = &[
244 &Self::COPY,
245 &Self::ZSTD,
246 &Self::LZMA,
247 &Self::LZMA2,
248 &Self::DEFLATE,
249 &Self::DEFLATE64,
250 &Self::BZIP2,
251 &Self::AES256SHA256,
252 &Self::BCJ_X86_FILTER,
253 &Self::BCJ_PPC_FILTER,
254 &Self::BCJ_IA64_FILTER,
255 &Self::BCJ_ARM_FILTER,
256 &Self::BCJ_ARM_THUMB_FILTER,
257 &Self::BCJ_SPARC_FILTER,
258 &Self::DELTA_FILTER,
259 &Self::BCJ2_FILTER,
260 ];
261
262 #[inline]
263 pub const fn name(&self) -> &'static str {
264 self.0
265 }
266
267 #[inline]
268 pub const fn id(&self) -> &'static [u8] {
269 self.1
270 }
271
272 #[inline]
273 pub fn by_id(id: &[u8]) -> Option<Self> {
274 Self::METHODS
275 .iter()
276 .find(|item| item.id() == id)
277 .cloned()
278 .cloned()
279 }
280}
281
282#[derive(Debug, Default, Clone)]
283pub struct StreamMap {
284 pub folder_first_pack_stream_index: Vec<usize>,
285 pub pack_stream_offsets: Vec<u64>,
286 pub folder_first_file_index: Vec<usize>,
287 pub file_folder_index: Vec<Option<usize>>,
288}
289
290#[derive(Debug, Clone, Copy)]
291pub(crate) struct StartHeader {
292 pub(crate) next_header_offset: u64,
293 pub(crate) next_header_size: u64,
294 pub(crate) next_header_crc: u64,
295}