1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
//! A library for reading/writing [Windows
//! cabinet](https://en.wikipedia.org/wiki/Cabinet_(file_format)) (CAB) files.
//!
//! # Overview
//!
//! CAB is an archive file format used by Windows.  A cabinet file can contain
//! multiple compressed files, which are divided into "folders" (no relation to
//! filesystem folders/directories); files in the same folder are compressed
//! together, and each folder in the cabinet can potentially use a different
//! compression scheme.  The CAB file format supports multiple different
//! compression schemes; this library can recognize all of them when reading
//! metadata for an existing cabinet file, but currently only supports
//! encoding/decoding some of them, as shown:
//!
//! | Compression                                                 | Supported |
//! |-------------------------------------------------------------|-----------|
//! | Uncompressed                                                | Yes       |
//! | MSZIP ([Deflate](https://en.wikipedia.org/wiki/DEFLATE))    | Yes       |
//! | [Quantum](https://en.wikipedia.org/wiki/Quantum_compression)| No        |
//! | [LZX](https://en.wikipedia.org/wiki/LZX_(algorithm))        | No        |
//!
//! # Example usage
//!
//! Use the `Cabinet` type to read an existing cabinet file:
//!
//! ```no_run
//! use cab;
//! use std::fs;
//! use std::io;
//!
//! let cab_file = fs::File::open("path/to/cabinet.cab").unwrap();
//! let mut cabinet = cab::Cabinet::new(cab_file).unwrap();
//! // List all files in the cabinet, with file sizes and compression types:
//! for folder in cabinet.folder_entries() {
//!     for file in folder.file_entries() {
//!         println!("File {} ({} B) is compressed with {:?}",
//!                  file.name(),
//!                  file.uncompressed_size(),
//!                  folder.compression_type());
//!     }
//! }
//! // Decompress a particular file in the cabinet and save it to disk:
//! let mut reader = cabinet.read_file("images/example.png").unwrap();
//! let mut writer = fs::File::create("out/example.png").unwrap();
//! io::copy(&mut reader, &mut writer).unwrap();
//! ```
//!
//! Creating a new cabinet file is a little more involved.  Because of how the
//! cabinet file is structured on disk, the library has to know the names of
//! all the files that will be in the cabinet up front, before it can start
//! writing anything to disk.  However, we don't want to have to hold all the
//! file **contents** in memory at once.  Therefore, cabinet creation happens
//! in two steps: first, create a `CabinetBuilder` and specify all filenames
//! and other metadata, and then second, stream each file's data into a
//! `CabinetWriter`, one at a time:
//!
//! ```no_run
//! use cab;
//! use std::fs;
//! use std::io;
//!
//! let mut cab_builder = cab::CabinetBuilder::new();
//! // Add a single file in its own folder:
//! cab_builder.add_folder(cab::CompressionType::None).add_file("img/foo.jpg");
//! // Add several more files, compressed together in a second folder:
//! {
//!     let folder = cab_builder.add_folder(cab::CompressionType::MsZip);
//!     folder.add_file("documents/README.txt");
//!     folder.add_file("documents/license.txt");
//!     // We can also specify metadata on individual files:
//!     {
//!         let file = folder.add_file("documents/hidden.txt");
//!         file.set_is_hidden(true);
//!         file.set_is_read_only(true);
//!     }
//! }
//! // Now, we'll actually construct the cabinet file on disk:
//! let cab_file = fs::File::create("path/to/cabinet.cab").unwrap();
//! let mut cab_writer = cab_builder.build(cab_file).unwrap();
//! while let Some(mut writer) = cab_writer.next_file().unwrap() {
//!     let mut reader = fs::File::open(writer.file_name()).unwrap();
//!     io::copy(&mut reader, &mut writer).unwrap();
//! }
//! // Print the file size of the cabinet file we just created:
//! let mut cab_file = cab_writer.finish().unwrap();
//! println!("Cabinet size: {} B", cab_file.metadata().unwrap().len());
//! ```

#![warn(missing_docs)]

extern crate byteorder;
extern crate chrono;
extern crate flate2;

mod internal;

pub use internal::builder::{CabinetBuilder, CabinetWriter, FileBuilder,
                            FileWriter, FolderBuilder};
pub use internal::cabinet::{Cabinet, FileEntries, FileEntry, FileReader,
                            FolderEntries, FolderEntry};
pub use internal::ctype::CompressionType;

// ========================================================================= //