Skip to content

Commit

Permalink
Merge pull request #44 from messense/odf
Browse files Browse the repository at this point in the history
Add support for Open Document formats
  • Loading branch information
bojand authored May 23, 2021
2 parents b4f9d58 + 9618b86 commit 9637d2f
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 18 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@ assert_eq!(kind.extension(), "foo");
- **xlsx** - `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`
- **ppt** - `application/vnd.ms-powerpoint`
- **pptx** - `application/vnd.openxmlformats-officedocument.presentationml.presentation`
- **odt** - `application/vnd.oasis.opendocument.text`
- **ods** - `application/vnd.oasis.opendocument.spreadsheet`
- **odp** - `application/vnd.oasis.opendocument.presentation`

#### Font

Expand Down
19 changes: 19 additions & 0 deletions src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,25 @@ matcher_map!(
"pptx",
matchers::doc::is_pptx
),
// OpenDocument
(
MatcherType::Doc,
"application/vnd.oasis.opendocument.text",
"odt",
matchers::odf::is_odt
),
(
MatcherType::Doc,
"application/vnd.oasis.opendocument.spreadsheet",
"ods",
matchers::odf::is_ods
),
(
MatcherType::Doc,
"application/vnd.oasis.opendocument.presentation",
"odp",
matchers::odf::is_odp
),
// Archive
(
MatcherType::Archive,
Expand Down
20 changes: 2 additions & 18 deletions src/matchers/doc.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use core::convert::TryInto;

use super::compare_bytes;

#[allow(clippy::upper_case_acronyms)]
#[derive(Debug, Eq, PartialEq)]
enum DocType {
Expand Down Expand Up @@ -123,24 +125,6 @@ fn ole2(buf: &[u8]) -> Option<DocType> {
Some(DocType::DOC)
}

fn compare_bytes(slice: &[u8], sub_slice: &[u8], start_offset: usize) -> bool {
let sl = sub_slice.len();

if start_offset + sl > slice.len() {
return false;
}

for (i, v) in slice.iter().skip(start_offset).take(sl).enumerate() {
let v2 = sub_slice[i];

if *v != v2 {
return false;
}
}

true
}

fn check_msooml(buf: &[u8], offset: usize) -> Option<DocType> {
if compare_bytes(buf, &[b'w', b'o', b'r', b'd', b'/'], offset) {
Some(DocType::DOCX)
Expand Down
19 changes: 19 additions & 0 deletions src/matchers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,24 @@ pub mod book;
pub mod doc;
pub mod font;
pub mod image;
pub mod odf;
pub mod text;
pub mod video;

pub(crate) fn compare_bytes(slice: &[u8], sub_slice: &[u8], start_offset: usize) -> bool {
let sl = sub_slice.len();

if start_offset + sl > slice.len() {
return false;
}

for (i, v) in slice.iter().skip(start_offset).take(sl).enumerate() {
let v2 = sub_slice[i];

if *v != v2 {
return false;
}
}

true
}
48 changes: 48 additions & 0 deletions src/matchers/odf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use super::compare_bytes;

#[derive(Debug, Eq, PartialEq)]
enum DocType {
Text,
Spreadsheet,
Presentation,
}

/// Returns whether a buffer is OpenDocument Text
pub fn is_odt(buf: &[u8]) -> bool {
odf(buf) == Some(DocType::Text)
}

/// Returns whether a buffer is OpenDocument Spreadsheet
pub fn is_ods(buf: &[u8]) -> bool {
odf(buf) == Some(DocType::Spreadsheet)
}

/// Returns whether a buffer is OpenDocument Presentation
pub fn is_odp(buf: &[u8]) -> bool {
odf(buf) == Some(DocType::Presentation)
}

fn odf(buf: &[u8]) -> Option<DocType> {
let signature = [b'P', b'K', 0x03, 0x04];

// start by checking for ZIP local file header signature
if !compare_bytes(buf, &signature, 0) {
return None;
}

// Check mimetype
if !compare_bytes(buf, b"mimetype", 0x1E) {
return None;
}

if compare_bytes(buf, b"vnd.oasis.opendocument.text", 0x32) {
return Some(DocType::Text);
}
if compare_bytes(buf, b"vnd.oasis.opendocument.spreadsheet", 0x32) {
return Some(DocType::Spreadsheet);
}
if compare_bytes(buf, b"vnd.oasis.opendocument.presentation", 0x32) {
return Some(DocType::Presentation);
}
None
}
Binary file added testdata/sample.odp
Binary file not shown.
Binary file added testdata/sample.ods
Binary file not shown.
Binary file added testdata/sample.odt
Binary file not shown.
25 changes: 25 additions & 0 deletions tests/odf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
mod common;

test_format!(
Doc,
"application/vnd.oasis.opendocument.text",
"odt",
odt,
"sample.odt"
);

test_format!(
Doc,
"application/vnd.oasis.opendocument.spreadsheet",
"ods",
ods,
"sample.ods"
);

test_format!(
Doc,
"application/vnd.oasis.opendocument.presentation",
"odp",
odp,
"sample.odp"
);

0 comments on commit 9637d2f

Please sign in to comment.