epub_parser/
zip_handler.rs1use crate::epub::Error;
2use std::fs::File;
3use std::io::{Read, Seek};
4use std::path::Path;
5use zip::ZipArchive;
6
7pub struct ZipHandler<R: Read + Seek> {
8 archive: ZipArchive<R>,
9}
10
11impl ZipHandler<File> {
12 pub fn new(path: &Path) -> Result<Self, Error> {
13 let file = File::open(path)?;
14 let archive = ZipArchive::new(file)?;
15 Ok(ZipHandler { archive })
16 }
17}
18
19impl<R: Read + Seek> ZipHandler<R> {
20 pub fn new_from_reader(reader: R) -> Result<Self, Error> {
21 let archive = ZipArchive::new(reader)?;
22 Ok(ZipHandler { archive })
23 }
24
25 pub fn get_opf_path(&mut self) -> Result<String, Error> {
26 let container_content = self.read_file("META-INF/container.xml")?;
27
28 let mut reader = quick_xml::Reader::from_str(&container_content);
29 let mut opf_path = String::new();
30
31 let mut buf = Vec::new();
32
33 loop {
34 match reader.read_event_into(&mut buf) {
35 Ok(quick_xml::events::Event::Start(ref e)) => {
36 let name = String::from_utf8_lossy(e.name().as_ref()).to_string();
37
38 if name == "rootfile" || name.ends_with(":rootfile") {
39 for attr_result in e.attributes() {
40 if let Ok(attr) = attr_result {
41 let attr_name =
42 String::from_utf8_lossy(attr.key.as_ref()).to_string();
43
44 if attr_name == "full-path" || attr_name.ends_with(":full-path") {
45 opf_path = attr
46 .decode_and_unescape_value(reader.decoder())?
47 .to_string();
48 break;
49 }
50 }
51 }
52 if !opf_path.is_empty() {
53 break;
54 }
55 }
56 }
57 Ok(quick_xml::events::Event::Empty(ref e)) => {
58 let name = String::from_utf8_lossy(e.name().as_ref()).to_string();
59
60 if name == "rootfile" || name.ends_with(":rootfile") {
61 for attr_result in e.attributes() {
62 if let Ok(attr) = attr_result {
63 let attr_name =
64 String::from_utf8_lossy(attr.key.as_ref()).to_string();
65
66 if attr_name == "full-path" || attr_name.ends_with(":full-path") {
67 opf_path = attr
68 .decode_and_unescape_value(reader.decoder())?
69 .to_string();
70 break;
71 }
72 }
73 }
74 if !opf_path.is_empty() {
75 break;
76 }
77 }
78 }
79 Ok(quick_xml::events::Event::Eof) => break,
80 Err(e) => return Err(Error::XmlError(e.to_string())),
81 _ => {}
82 }
83 buf.clear();
84 }
85
86 if opf_path.is_empty() {
87 return Err(Error::MissingOpf);
88 }
89
90 Ok(opf_path)
91 }
92
93 pub fn read_file(&mut self, path: &str) -> Result<String, Error> {
94 let mut file = self.archive.by_name(path)?;
95 let mut content = String::new();
96 file.read_to_string(&mut content)?;
97 Ok(content)
98 }
99
100 pub fn read_file_as_bytes(&mut self, path: &str) -> Result<Vec<u8>, Error> {
101 let mut file = self.archive.by_name(path)?;
102 let mut content = Vec::new();
103 file.read_to_end(&mut content)?;
104 Ok(content)
105 }
106}