pub mod error;
pub mod model;
pub mod parser;
pub mod reader;
use crate::extraction::hwp::model::HwpDocument;
use error::{HwpError, Result};
use parser::{FileHeader, parse_body_text, parse_doc_info};
use reader::CfbReader;
pub(crate) fn extract_hwp_document(bytes: &[u8]) -> Result<HwpDocument> {
let mut cfb = CfbReader::from_bytes(bytes)?;
let header_data = cfb.read_stream("FileHeader")?;
let header = FileHeader::parse(header_data)?;
if header.is_encrypted() {
return Err(HwpError::UnsupportedVersion(
"Password-encrypted HWP documents are not supported".to_string(),
));
}
let mut doc = HwpDocument::default();
if cfb.stream_exists("DocInfo") {
let doc_info_data = cfb.read_stream("DocInfo")?;
if let Ok(char_shapes) = parse_doc_info(doc_info_data) {
doc.char_shapes = char_shapes;
}
}
let mut streams = cfb.list_streams();
streams.sort();
for path in streams {
if path.starts_with("BodyText/Section") {
let section_data = cfb.read_stream(&path)?;
if let Ok(sections) = parse_body_text(section_data, header.is_compressed()) {
doc.sections.extend(sections);
}
}
}
for path in cfb.list_streams() {
if path.starts_with("BinData/") {
let image_data = cfb.read_stream(&path)?;
doc.images.push(model::HwpImage {
name: path.clone(),
data: image_data,
});
}
}
Ok(doc)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_extract_invalid_hwp() {
let bytes = b"Not a valid HWP file";
assert!(extract_hwp_document(bytes).is_err());
}
}