diff --git a/Cargo.toml b/Cargo.toml index 76f499c..1030817 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,9 @@ exclude = ["examples/**", "axmldecoder-printer/**"] [dependencies] byteorder = "1.4.3" -deku = "~0.16" -indexmap = "1.9.2" +# TODO: move to crates.io when the feature is available +# default attribute for enums not yet available at version realeased on crates.io +# https://github.com/sharksforarms/deku/pull/335 +deku = { git = "https://github.com/sharksforarms/deku" } +indexmap = "2.0" thiserror = "1.0.37" diff --git a/axmldecoder-printer/src/main.rs b/axmldecoder-printer/src/main.rs index 99ee1ce..41ab70f 100644 --- a/axmldecoder-printer/src/main.rs +++ b/axmldecoder-printer/src/main.rs @@ -13,7 +13,7 @@ fn main() -> Result<()> { let root = xml.get_root().as_ref().unwrap(); let mut s = String::new(); s.push_str("\n"); - format_xml(&root, 0_usize, &mut s); + format_xml(root, 0_usize, &mut s); let s = s.trim().to_string(); println!("{}", s); @@ -27,7 +27,7 @@ fn main() -> Result<()> { let root = xml.get_root().as_ref().unwrap(); let mut s = String::new(); s.push_str("\n"); - format_xml(&root, 0_usize, &mut s); + format_xml(root, 0_usize, &mut s); let s = s.trim().to_string(); println!("{}", s); @@ -42,19 +42,19 @@ fn format_xml(e: &Node, level: usize, output: &mut String) { output.push_str(&format!( "{:indent$}{}\n", "", - &format_start_element(&e), + &format_start_element(e), indent = level * 2 )); for child in e.get_children() { - format_xml(&child, level + 1, output) + format_xml(child, level + 1, output) } if !e.get_children().is_empty() { output.push_str(&format!( "{:indent$}{}\n", "", - &format_end_element(&e), + &format_end_element(e), indent = level * 2 )); } @@ -63,7 +63,7 @@ fn format_xml(e: &Node, level: usize, output: &mut String) { output.push_str(&format!( "{:indent$}{}\n", "", - &format_cdata(&e, level), + &format_cdata(e, level), indent = level * 2 )); } @@ -74,7 +74,7 @@ fn format_cdata(e: &Cdata, level: usize) -> String { let indent = format!("{:indent$}", "", indent = level * 2); let mut s = String::new(); s.push_str(""); s } diff --git a/examples/AndroidManifest_malformed.xml b/examples/AndroidManifest_malformed.xml new file mode 100644 index 0000000..982ae06 Binary files /dev/null and b/examples/AndroidManifest_malformed.xml differ diff --git a/src/binaryxml.rs b/src/binaryxml.rs index 049c7b8..62c682a 100644 --- a/src/binaryxml.rs +++ b/src/binaryxml.rs @@ -19,9 +19,12 @@ pub(crate) struct BinaryXmlDocument { #[deku(type = "u16")] pub(crate) enum ResourceType { NullType = 0x000, + StringPool = 0x0001, Table = 0x0002, Xml = 0x0003, + + // Chunk types in XmlNodeType XmlStartNameSpace = 0x0100, XmlEndNameSpace = 0x101, XmlStartElement = 0x0102, @@ -29,10 +32,14 @@ pub(crate) enum ResourceType { XmlCdata = 0x0104, XmlLastChunk = 0x017f, XmlResourceMap = 0x0180, + TablePackage = 0x0200, TableType = 0x0201, TableTypeSpec = 0x0202, TableLibrary = 0x0203, + + #[deku(id = "0xffff", default)] + Unknown = 0xffff, } #[derive(Clone, Debug, DekuRead, DekuWrite)] @@ -70,6 +77,9 @@ pub(crate) enum XmlNodeType { XmlEndElement(XmlEndElement), #[deku(id = "ResourceType::XmlCdata")] XmlCdata(XmlCdata), + + #[deku(id = "ResourceType::NullType", default)] + Unknown, } #[derive(Debug, DekuRead, DekuWrite)] @@ -145,6 +155,9 @@ pub(crate) enum ResourceValueType { ColorRgb8 = 0x1d, ColorArgb4 = 0x1e, ColorRgb4 = 0x1f, + + #[deku(id = "0xff", default)] + Unknown = 0xffff, } #[derive(Debug, DekuRead, DekuWrite)] diff --git a/src/lib.rs b/src/lib.rs index 4687016..87f32af 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -70,16 +70,24 @@ mod tests { use std::path::PathBuf; #[test] - fn test_parse() { + fn test_parse() -> std::io::Result<()> { let mut examples = PathBuf::from(env!("CARGO_MANIFEST_DIR")); examples.push("examples"); - for entry in std::fs::read_dir(examples).unwrap() { - let entry = entry.unwrap(); - let mut f = File::open(entry.path()).unwrap(); + for entry in std::fs::read_dir(&examples)? { + let entry = entry?; + println!("Processing file: {}", entry.path().display()); + let mut f = File::open(entry.path())?; let mut buf = Vec::new(); - f.read_to_end(&mut buf).unwrap(); - parse(&buf).unwrap_or_else(|_| panic!("{} failed to parse", entry.path().display())); + f.read_to_end(&mut buf)?; + let result = parse(&buf); + assert!( + result.is_ok(), + "Failed to parse file: {}", + entry.path().display() + ); } + + Ok(()) } } diff --git a/src/xml.rs b/src/xml.rs index 35eedb6..1f43e99 100644 --- a/src/xml.rs +++ b/src/xml.rs @@ -67,6 +67,10 @@ impl XmlDocument { .unwrap() .insert_children(Node::Cdata(cdata)); } + _ => { + println!("Unknown node type: {:?}", node.element); + continue; + } }; } @@ -124,10 +128,17 @@ impl XmlDocument { } for attr in &e.attributes { - let ns = string_pool.get(usize::try_from(attr.ns).unwrap()); - let name = string_pool - .get(usize::try_from(attr.name).unwrap()) - .ok_or(ParseError::StringNotFound(attr.name))?; + let ns = match usize::try_from(attr.ns) { + Ok(val) => string_pool.get(val), + Err(_) => continue, + }; + let name = match usize::try_from(attr.name) { + Ok(val) => match string_pool.get(val) { + Some(n) => n, + None => continue, + }, + Err(_) => continue, + }; let value = attr.typed_value.get_value(string_pool); let mut final_name = String::new();