use crate::signatures::common::{SignatureError, SignatureResult, CONFIDENCE_HIGH};
use crate::structures::xz::{parse_xz_footer, parse_xz_header};
use aho_corasick::AhoCorasick;
pub const DESCRIPTION: &str = "XZ compressed data";
pub fn xz_magic() -> Vec<Vec<u8>> {
vec![b"\xFD\x37\x7a\x58\x5a\x00".to_vec()]
}
pub fn xz_parser(file_data: &[u8], offset: usize) -> Result<SignatureResult, SignatureError> {
let mut result = SignatureResult {
offset,
description: DESCRIPTION.to_string(),
confidence: CONFIDENCE_HIGH,
..Default::default()
};
if let Ok(header_size) = parse_xz_header(&file_data[offset..]) {
if let Some(xz_stream_data) = file_data.get(offset + header_size..) {
if let Ok(stream_size) = xz_stream_size(xz_stream_data) {
result.size = header_size + stream_size;
result.description =
format!("{}, total size: {} bytes", result.description, result.size);
return Ok(result);
}
}
};
Err(SignatureError)
}
fn xz_stream_size(xz_data: &[u8]) -> Result<usize, SignatureError> {
const FOOTER_MAGIC_OFFSET: usize = 10;
let eof_pattern = vec![b"YZ"];
let grep = AhoCorasick::new(eof_pattern).unwrap();
for eof_match in grep.find_overlapping_iter(xz_data) {
let match_offset: usize = eof_match.start();
let footer_start: usize = match_offset - FOOTER_MAGIC_OFFSET;
if (footer_start % 4) == 0 {
if let Some(footer_data) = xz_data.get(footer_start..) {
if let Ok(footer_size) = parse_xz_footer(footer_data) {
return Ok(footer_start + footer_size);
}
}
}
}
Err(SignatureError)
}