ole/
entry.rs

1//             DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
2//                    Version 2, December 2004
3//
4// Copyright (C) 2018 Thomas Bailleux <thomas@bailleux.me>
5//
6// Everyone is permitted to copy and distribute verbatim or modified
7// copies of this license document, and changing it is allowed as long
8// as the name is changed.
9//
10//            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
11//   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
12//
13//  0. You just DO WHAT THE FUCK YOU WANT TO.
14//
15// Author: zadig <thomas chr(0x40) bailleux.me>
16
17use std;
18
19#[derive(Debug)]
20pub(crate) enum NodeColour {
21  Red,
22  Black
23}
24
25impl NodeColour {
26  fn from(t: u8) -> Result<NodeColour, super::error::Error> {
27    match t {
28      0 => Ok(NodeColour::Red),
29      1 => Ok(NodeColour::Black),
30      _ => Err(super::error::Error::NodeTypeUnknown)
31    }
32  }
33}
34
35impl std::fmt::Display for NodeColour {
36  fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
37    match *self {
38      NodeColour::Red => write!(f, "RED"),
39      NodeColour::Black => write!(f, "BLACK")
40    }
41  }
42}
43
44#[derive(PartialEq, Debug, Clone, Copy)]
45pub enum EntryType {
46  /// Empty entry.
47  Empty,
48
49  /// Storage, i.e. a directory.
50  UserStorage,
51
52  /// Stream, i.e. a file.
53  UserStream,
54
55  /// LockBytes (unknown usage).
56  LockBytes,
57
58  /// Property (unknown usage).
59  Property,
60
61  /// Root storage.
62  RootStorage
63}
64
65impl EntryType {
66  fn from(t: u8) -> Result<EntryType, super::error::Error> {
67    match t {
68      0 => Ok(EntryType::Empty),
69      1 => Ok(EntryType::UserStorage),
70      2 => Ok(EntryType::UserStream),
71      3 => Ok(EntryType::LockBytes),
72      4 => Ok(EntryType::Property),
73      5 => Ok(EntryType::RootStorage),
74      _ => Err(super::error::Error::NodeTypeUnknown)
75    }
76  }
77}
78
79impl std::fmt::Display for EntryType {
80  fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
81    match *self {
82      EntryType::Empty => write!(f, "Empty"),
83      EntryType::UserStorage => write!(f, "User storage"),
84      EntryType::UserStream => write!(f, "User stream"),
85      EntryType::LockBytes => write!(f, "?? Lock bytes ??"),
86      EntryType::Property => write!(f, "?? Property ??"),
87      EntryType::RootStorage => write!(f, "Root storage")
88    }
89  }
90}
91
92/// An entry in an OLE file.
93///
94/// An entry means a stream or a storage.
95/// A stream is a file, and a storage is a folder.
96///
97/// # Basic Example
98///
99/// ```
100/// use ole::Reader;
101///
102/// let mut parser =
103///       Reader::from_path("assets/Thumbs.db").unwrap();
104///
105/// let entry = parser.iterate().next().unwrap();
106/// println!("Name of the entry: {}", entry.name());
107/// println!("Type of the entry: {}", entry._type());
108/// println!("Size of the entry: {}", entry.len());
109/// ```
110#[derive(Debug)]
111pub struct Entry {
112
113  /// ID of the entry.
114  id: u32,
115
116  /// Name of the stream or the storage.
117  name: std::string::String,
118
119  /// Type of the entry.
120  entry_type: EntryType,
121
122  /// Color of the entry (see <https://en.wikipedia.org/wiki/Red%E2%80%93black_tree>)
123  color: NodeColour,
124
125  /// ID of the left child entry.
126  left_child_node: u32,
127
128  /// ID of the right child entry.
129  right_child_node: u32,
130
131  /// ID of the root node
132  root_node: u32,
133
134  /// UID of the entry.
135  identifier: std::vec::Vec<u8>, // 16 bytes
136
137  /// Flags of the entry.
138  flags: std::vec::Vec<u8>, // 4 bytes
139
140  /// Creation time.
141  creation_time: u64,
142
143  /// Last modification time.
144  last_modification_time: u64,
145
146  /// Chain of secID which hold the stream or the storage
147  sec_id_chain: std::vec::Vec<u32>,
148
149  /// Size of the entry.
150  size: usize,
151
152  /// Array of the children's DirIDs
153  children_nodes: std::vec::Vec<u32>,
154
155  /// DirID of the parent
156  parent_node: Option<u32>
157}
158
159impl Entry {
160
161  fn from_slice(sector: &[u8], dir_id: u32)
162      -> Result<Entry, super::error::Error> {
163    use util::FromSlice;
164    let entry = Entry {
165      id: dir_id,
166      name: Entry::build_name(&sector[0 .. 64]),
167      entry_type: EntryType::from(sector[66])?,
168      color: NodeColour::from(sector[67])?,
169      left_child_node: u32::from_slice(&sector[68 .. 72]),
170      right_child_node: u32::from_slice(&sector[72 .. 76]),
171      root_node: u32::from_slice(&sector[76 .. 80]),
172      identifier: sector[80 .. 96].to_vec(),
173      flags: sector[96 .. 100].to_vec(),
174      creation_time: u64::from_slice(&sector[100 .. 108]),
175      last_modification_time: u64::from_slice(&sector[108 .. 116]),
176      sec_id_chain: vec![u32::from_slice(&sector[116 .. 120])],
177      size: usize::from_slice(&sector[120 .. 124]),
178      children_nodes: std::vec::Vec::new(),
179      parent_node: None
180    };
181
182
183    Ok(entry)
184
185  }
186
187  fn build_name(array: &[u8]) -> std::string::String {
188    let mut name = std::string::String::new();
189
190    let mut i = 0usize;
191    while i < 64 && array[i] != 0 {
192      name.push(array[i] as char);
193      i = i + 2;
194    }
195
196    name
197  }
198
199  /// Returns the ID of the entry.
200  pub fn id(&self) -> u32 {
201    self.id
202  }
203
204  /// Returns the creation time of the entry (could be 0)
205  pub fn creation_time(&self) -> u64 {
206    self.creation_time
207  }
208
209
210  /// Returns the last modification time of the entry (could be 0)
211  pub fn last_modification_time(&self) -> u64 {
212    self.last_modification_time
213  }
214
215  /// Returns the name of the entry.
216  pub fn name(&self) -> &str {
217    &self.name
218  }
219
220  /// Returns the type of the entry.
221  pub fn _type(&self) -> EntryType {
222    self.entry_type
223  }
224
225  /// Returns the size of the entry
226  pub fn len(&self) -> usize {
227    self.size
228  }
229
230  /// Returns the DirID of the left child node
231  pub fn left_child_node(&self) -> u32 {
232    self.left_child_node
233  }
234
235  /// Returns the DirID of the right child node
236  pub fn right_child_node(&self) -> u32 {
237    self.right_child_node
238  }
239
240  /// Returns the DirID of the parent, if exists
241  pub fn parent_node(&self) -> Option<u32> {
242    self.parent_node
243  }
244
245  /// Returns the DirIDs of the children, if exists
246  pub fn children_nodes(&self) -> &std::vec::Vec<u32> {
247    &self.children_nodes
248  }
249}
250
251impl std::fmt::Display for Entry {
252  fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
253    write!(f, "Entry #{}. Type: {}, Color: {}, Name: {},
254      Size: {}. SecID chain: {:?}",
255      self.id, self.entry_type, self.color, &self.name,
256      self.size, self.sec_id_chain)
257  }
258}
259
260
261/// Slice of the content of the entry.
262///
263/// This is not an ordinary slice, because OLE files are like FAT system:
264/// they are based on sector and SAT. Therefore, a stream can be fragmented
265/// through the file.
266///
267/// # Basic example
268///
269/// ```
270/// use ole::Reader;
271/// use std::io::Read;
272/// let mut parser =
273///       Reader::from_path("assets/Thumbs.db").unwrap();
274///
275/// let entry = parser.iterate().next().unwrap();
276/// let mut slice = parser.get_entry_slice(entry).unwrap();
277/// // Read the first 42 bytes of the entry;
278/// let mut buf = [0u8; 42];
279/// let nread = slice.read(&mut buf).unwrap();
280///
281/// ```
282pub struct EntrySlice<'s> {
283
284  /// Chunk size, i.e. size of the sector.
285  max_chunk_size: usize,
286
287  /// List of slices.
288  chunks: std::vec::Vec<&'s [u8]>,
289
290  /// How many bytes which have been already read.
291  read: usize,
292
293  /// Total size of slice.
294  total_size: usize,
295
296  /// Real size of all chunks
297  real_size: usize
298}
299
300impl<'s> EntrySlice<'s> {
301  fn new(max_chunk_size: usize, size: usize) -> EntrySlice<'s> {
302    EntrySlice {
303      max_chunk_size: max_chunk_size,
304      chunks: std::vec::Vec::new(),
305      read: 0usize,
306      total_size: size,
307      real_size: 0
308    }
309  }
310
311  fn add_chunk(&mut self, chunk: &'s [u8]) {
312    self.real_size += chunk.len();
313    self.chunks.push(chunk);
314  }
315
316  /// Returns the length of the slice, therefore the length of the entry.
317  pub fn len(&self) -> usize {
318    self.total_size
319  }
320
321  /// Returns the real length of all chunks
322  pub fn real_len(&self) -> usize {
323    self.real_size
324  }
325}
326
327impl<'s> std::io::Read for EntrySlice<'s> {
328
329  fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
330    let to_read = std::cmp::min(buf.len(), self.total_size - self.read);
331    let result: Result<usize, std::io::Error>;
332    if to_read == 0 {
333      result = Ok(0usize);
334    } else {
335      let mut offset = self.read;
336      let mut read = 0;
337      while read != to_read {
338        let chunk_index = offset / self.max_chunk_size;
339        if chunk_index >= self.chunks.len() {
340          break;
341        }
342        let chunk = &self.chunks[chunk_index];
343        let local_offset = offset % self.max_chunk_size;
344        let end = std::cmp::min(local_offset + to_read - read,
345        self.max_chunk_size);
346        let slice = &chunk[local_offset .. end];
347        for u in slice {
348          buf[read] = *u;
349          read += 1;
350          self.read += 1;
351        }
352        offset = self.read;
353      }
354      result = Ok(read);
355    }
356
357    result
358  }
359}
360
361
362
363
364impl<'ole> super::ole::Reader<'ole> {
365
366
367  /// Returns the slice for the entry.
368  pub fn get_entry_slice(&self, entry: &Entry) ->
369    Result<EntrySlice, super::error::Error> {
370
371    let entry_slice: EntrySlice;
372    let size = entry.size;
373    if size == 0 {
374      Err(super::error::Error::EmptyEntry)
375    } else {
376      if &size < self.minimum_standard_stream_size.as_ref().unwrap() {
377        entry_slice = self.get_short_stream_slices(&entry.sec_id_chain, size)?;
378      } else {
379        entry_slice = self.get_stream_slices(&entry.sec_id_chain, size)?;
380      }
381      Ok(entry_slice)
382    }
383  }
384
385  pub(crate) fn build_directory_entries(&mut self)
386      -> Result<(), super::error::Error> {
387    let n_entry_by_sector = self.sec_size.as_ref().unwrap()
388      / super::constants::DIRECTORY_ENTRY_SIZE;
389    let mut entries = std::vec::Vec::<Entry>::with_capacity(
390      self.dsat.as_ref().unwrap().len() * n_entry_by_sector);
391
392    let mut k = 0usize;
393    for i in 0 .. self.dsat.as_ref().unwrap().len() {
394      let sector_index = self.dsat.as_ref().unwrap()[i];
395      let sector = self.read_sector(sector_index as usize)?;
396      for l in 0 .. n_entry_by_sector {
397        let entry = Entry::from_slice(&sector[l
398          * super::constants::DIRECTORY_ENTRY_SIZE .. (l + 1)
399          * super::constants::DIRECTORY_ENTRY_SIZE], k as u32)?;
400        entries.push(entry);
401        k = k + 1;
402      }
403    }
404    let stream_size = *self.minimum_standard_stream_size.as_ref().unwrap();
405    for i in 0 .. entries.len() {
406      let entry = &mut entries[i];
407      match entry.entry_type {
408        EntryType::UserStream => {
409          let start_index = entry.sec_id_chain.pop().unwrap();
410          if entry.size < stream_size {
411            entry.sec_id_chain = self.build_chain_from_ssat(start_index);
412          } else {
413            entry.sec_id_chain = self.build_chain_from_sat(start_index);
414          }
415        },
416        EntryType::RootStorage => {
417          self.root_entry = Some(i as u32);
418          let start_index = entry.sec_id_chain.pop().unwrap();
419          entry.sec_id_chain = self.build_chain_from_sat(start_index);
420        },
421        _ => {}
422      }
423    }
424    self.entries = Some(entries);
425    self.build_entry_tree(0, None);
426    Ok(())
427  }
428
429  fn get_short_stream_slices(&self, chain: &std::vec::Vec<u32>, size: usize)
430  -> Result<EntrySlice, super::error::Error> {
431    let ssector_size = *self.short_sec_size.as_ref().unwrap();
432    let mut entry_slice = EntrySlice::new(ssector_size, size);
433    let short_stream_chain =
434    &self.entries.as_ref().unwrap()[0].sec_id_chain.clone();
435    let n_per_sector = *self.sec_size.as_ref().unwrap() /
436      ssector_size;
437    let mut total_read = 0;
438    for ssector_id in chain {
439      let sector_index = short_stream_chain[*ssector_id as usize / n_per_sector];
440      let sector = self.read_sector(sector_index as usize)?;
441      let ssector_index = *ssector_id as usize % n_per_sector;
442      let start = ssector_index as usize * ssector_size;
443      let end = start + std::cmp::min(ssector_size, size - total_read);
444      entry_slice.add_chunk(&sector[start .. end]);
445      total_read += end - start;
446    }
447    Ok(entry_slice)
448  }
449
450  fn get_stream_slices(&self, chain: &std::vec::Vec<u32>, size: usize)
451  -> Result<EntrySlice, super::error::Error> {
452    let sector_size = *self.sec_size.as_ref().unwrap();
453    let mut entry_slice = EntrySlice::new(sector_size, size);
454    let mut total_read = 0;
455    for sector_id in chain {
456      let sector = self.read_sector(*sector_id as usize)?;
457      let start = 0usize;
458      let end = std::cmp::min(sector_size, size - total_read);
459      entry_slice.add_chunk(&sector[start .. end]);
460      total_read += end - start;
461    }
462    Ok(entry_slice)
463  }
464
465  fn build_entry_tree(&mut self, id: u32, parent_id: Option<u32>) {
466
467    if id != super::constants::FREE_SECID_U32 {
468
469      // Register the parent id for the current node
470      self.entries.as_mut().unwrap()[id as usize].parent_node = parent_id;
471
472      // Register as child
473      if parent_id.is_some() {
474        self.entries.as_mut().unwrap()[parent_id.unwrap() as usize]
475          .children_nodes.push(id);
476      }
477
478      let node_type = self.entries.as_ref().unwrap()[id as usize]._type();
479
480      if node_type == EntryType::RootStorage || node_type ==
481        EntryType::UserStorage {
482          let child = self.entries.as_mut().unwrap()[id as usize].root_node;
483          self.build_entry_tree(child, Some(id));
484      }
485      let left_child = self.entries.as_mut().unwrap()[id as usize]
486          .left_child_node();
487      let right_child = self.entries.as_mut().unwrap()[id as usize]
488          .right_child_node();
489      let n = self.entries.as_ref().unwrap().len() as u32;
490      if left_child < n {
491        self.build_entry_tree(left_child, parent_id);
492      }
493      if right_child < n {
494        self.build_entry_tree(right_child, parent_id);
495      }
496    }
497  }
498}