mdsteele / rust-cfb

Rust library for reading/writing Compound File Binary (structured storage) files
MIT License
44 stars 20 forks source link

Can't Read Certain Streams (Property Sets) #32

Closed ExpoundingTurtle closed 2 years ago

ExpoundingTurtle commented 2 years ago

This doesn't seem to be able to read Property Sets or Properties. It sees them as a stream when listing out information, but when you try to open it as a stream it says it isn't one.

If I list all of the entries in the root I get.

Root Storage →
  - name = Sheet6 | length = 57 | is_storage=false | is_stream=true | path = /Sheet6
  - name = Sheet12 | length = 272 | is_storage=false | is_stream=true | path = /Sheet12
  - name = Sheet22 | length = 272 | is_storage=false | is_stream=true | path = /Sheet22
  - name = Sheet32 | length = 232 | is_storage=false | is_stream=true | path = /Sheet32
  - name = Sheet41 | length = 288 | is_storage=false | is_stream=true | path = /Sheet41
  - name = Sheet51 | length = 232 | is_storage=false | is_stream=true | path = /Sheet51
  - name = PSMroots | length = 132 | is_storage=false | is_stream=true | path = /PSMroots
  - name = AppObject | length = 4 | is_storage=false | is_stream=true | path = /AppObject
  - name = JSitesList | length = 8 | is_storage=false | is_stream=true | path = /JSitesList
  - name = DocVersion2 | length = 66 | is_storage=false | is_stream=true | path = /DocVersion2
  - name = DocVersion3 | length = 240 | is_storage=false | is_stream=true | path = /DocVersion3
  - name = PSMcluster0 | length = 3799 | is_storage=false | is_stream=true | path = /PSMcluster0
  - name = PSMspacemap | length = 0 | is_storage=true | is_stream=false | path = /PSMspacemap
  - name = StyleCluster | length = 2361 | is_storage=false | is_stream=true | path = /StyleCluster
  - name = PSMclustertable | length = 400 | is_storage=false | is_stream=true | path = /PSMclustertable
  - name = PSMsegmenttable | length = 12 | is_storage=false | is_stream=true | path = /PSMsegmenttable
  - name = SummaryInformation | length = 288 | is_storage=false | is_stream=true | path = /SummaryInformation
  - name = DocumentSummaryInformation | length = 124 | is_storage=false | is_stream=true | path = /DocumentSummaryInformation
  - name = Dynamic Attributes Metadata | length = 28 | is_storage=false | is_stream=true | path = /Dynamic Attributes Metadata
  - name = Unclustered Dynamic Attributes | length = 244 | is_storage=false | is_stream=true | path = /Unclustered Dynamic Attributes

You can see SummaryInformation in that and its listed as a stream with a path of /SummaryInformation. But then when I try to read that stream I get.

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Custom { kind: NotFound, error: "No such stream: \"/SummaryInformation\"" }', cfb_lab/src/main.rs:27:62

Sorce code is →

use cfb;
use std::{io::{Read, Seek, SeekFrom, Write}, fs::File};
use intercom::{com_library, com_class, com_interface, ComResult};
use chrono::prelude::{DateTime, Utc};

fn main(){

    // Path to file
    let path = "/Users/blakebennett/Dropbox/Programming/rust/radix-labratory/testfiles/Circle.igr";

    // Open an existing compound file in read-write mode.
    let mut comp = cfb::open_rw(path).unwrap();

    let root_entry = comp.root_entry();
    log_entry(root_entry);

    // Open root of all data objects.
    let root = comp.read_root_storage();
    log_entries(root, "Root Storage →");

    // Read in all the data from one of the streams in that compound file.
    let storage_psmspacemap = comp.read_storage("/PSMspacemap").unwrap();
    log_entries(storage_psmspacemap, "PSMspacemap →");

    // Open a sheet and read in all the data.
    let mut summary = comp.open_stream("/SummaryInformation").unwrap();

}

/// Given a stream, logs its data with a header. 
fn log_stream_data(data: Vec<u8>, header: &str){
    println!("{}", header);
    println!("  {:02X?}", data);
}

fn log_entry(entry: cfb::Entry) {
    let name = entry.name();
    let length = entry.len();
    let is_storage = entry.is_storage();
    let is_stream = entry.is_stream();
    let internal_path = entry.path();

    println!("  - name = {} | length = {} | is_storage={} | is_stream={} | path = {}", name, length, is_storage, is_stream, internal_path.as_os_str().to_str().unwrap());
}

/// Given a set of Entries, logs their data with a header.
fn log_entries(entries: cfb::Entries, header: &str){
    println!("{}", header);
    for entry in entries {
        log_entry(entry);
    }
}
ExpoundingTurtle commented 2 years ago

It was some invisible symbol that gets printed as nothing but does in fact exists. Maybe some old white space nonsense, who knows. But I figured it out in any case.