CAB API Reference
CAB::Decompressor
Class Overview
The [Cabriolet::CAB::Decompressor](lib/cabriolet/cab/decompressor.rb) class handles extraction and parsing of Microsoft Cabinet archives.
module Cabriolet
module CAB
class Decompressor
# Main decompressor implementation
end
end
endConstructor
new(source, options = {})
Creates a new CAB decompressor instance.
Parameters:
-
source(String, IO, Handle) - Cabinet file path, IO object, or custom handle -
options(Hash) - Optional configuration
Options:
-
:salvage(Boolean) - Enable salvage mode for corrupted archives (default:false) -
:verify_checksums(Boolean) - Verify file checksums (default:true) -
:read_buffer(Integer) - Read buffer size in bytes (default:32768) -
:io_system(IOSystem) - Custom I/O system (default:System::IOSystem.new) -
:offset(Integer) - Starting offset for embedded cabinets (default:0)
Returns: New Decompressor instance
Raises: * [Cabriolet::IOError](lib/cabriolet/errors.rb:10) - File not found or not readable * [Cabriolet::InvalidHeaderError](lib/cabriolet/errors.rb:25) - Invalid cabinet header * [Cabriolet::UnsupportedFormatError](lib/cabriolet/errors.rb:50) - Unsupported cabinet version
Example:
# From file path
decompressor = Cabriolet::CAB::Decompressor.new('archive.cab')
# With options
decompressor = Cabriolet::CAB::Decompressor.new(
'archive.cab',
salvage: true,
verify_checksums: false
)
# From IO object
File.open('archive.cab', 'rb') do |io|
decompressor = Cabriolet::CAB::Decompressor.new(io)
end
# From memory
data = File.binread('archive.cab')
memory_handle = Cabriolet::System::MemoryHandle.new(data)
decompressor = Cabriolet::CAB::Decompressor.new(memory_handle)Thread Safety: Constructor is thread-safe. The returned instance is not thread-safe by default.
Instance Methods
cabinet
Returns the cabinet metadata.
Returns: [Cabriolet::Models::Cabinet](lib/cabriolet/models/cabinet.rb:5)
Example:
cabinet = decompressor.cabinet
puts "Version: #{cabinet.version}"
puts "File count: #{cabinet.file_count}"
puts "Set ID: #{cabinet.set_id}" files
Returns array of all files in the cabinet.
Returns: Array<Cabriolet::Models::File>
Example:
decompressor.files.each do |file|
puts "#{file.filename}: #{file.uncompressed_size} bytes"
end folders
Returns array of all compression folders.
Returns: Array<Cabriolet::Models::Folder>
Example:
decompressor.folders.each_with_index do |folder, idx|
puts "Folder #{idx}: #{folder.compression_type}"
end extract_file(filename, output_path, options = {})
Extracts a single file from the cabinet.
Parameters:
-
filename(String) - File to extract -
output_path(String) - Destination path -
options(Hash) - Optional configuration
Options:
-
:overwrite(Boolean) - Overwrite existing files (default:true) -
:preserve_attributes(Boolean) - Preserve file attributes (default:true) -
:preserve_times(Boolean) - Preserve modification times (default:true)
Returns: true on success
Raises: * [Cabriolet::IOError](lib/cabriolet/errors.rb:10) - Write error * [Cabriolet::DecompressionError](lib/cabriolet/errors.rb:35) - Decompression failed * [Cabriolet::ChecksumError](lib/cabriolet/errors.rb:40) - Checksum mismatch
Example:
# Basic extraction
decompressor.extract_file('readme.txt', 'output/readme.txt')
# With options
decompressor.extract_file(
'data.bin',
'output/data.bin',
overwrite: false,
preserve_times: true
) extract_all(output_dir, options = {})
Extracts all files from the cabinet.
Parameters:
-
output_dir(String) - Output directory -
options(Hash) - Optional configuration (same asextract_file)
Returns: Integer - Number of files extracted
Raises: Same as extract_file
Example:
# Extract all files
count = decompressor.extract_all('output')
puts "Extracted #{count} files"
# With pattern filter
count = decompressor.extract_all('output', filter: '*.txt') extract_to_memory(filename)
Extracts a file to memory without writing to disk.
Parameters:
-
filename(String) - File to extract
Returns: String (binary) - Extracted file contents
Raises: Same as extract_file
Example:
# Extract to memory
data = decompressor.extract_to_memory('config.json')
config = JSON.parse(data)
# Process binary data
image_data = decompressor.extract_to_memory('logo.png')
process_image(image_data) test
Tests cabinet integrity without extracting.
Returns: Hash with test results
Example:
result = decompressor.test
if result[:valid]
puts "Cabinet is valid"
puts "Files: #{result[:file_count]}"
else
puts "Cabinet is corrupted"
puts "Errors: #{result[:errors].join(', ')}"
end find(pattern)
Finds files matching a pattern.
Parameters:
-
pattern(String, Regexp) - Search pattern
Returns: Array<Cabriolet::Models::File> - Matching files
Example:
# Find by extension
txt_files = decompressor.find('*.txt')
# Find by regexp
log_files = decompressor.find(/\.log$/i)
# Find in subdirectory
docs = decompressor.find('docs/**/*.md') close
Closes the decompressor and releases resources.
Returns: nil
Example:
decompressor = Cabriolet::CAB::Decompressor.new('archive.cab')
begin
decompressor.extract_all('output')
ensure
decompressor.close
end
# Or use block form
Cabriolet::CAB::Decompressor.open('archive.cab') do |decomp|
decomp.extract_all('output')
end # Automatically closedClass Methods
search(filename, options = {})
Searches for embedded cabinets within a file.
Parameters:
-
filename(String) - File to search -
options(Hash) - Search options
Options:
-
:min_size(Integer) - Minimum cabinet size (default:1000) -
:max_results(Integer) - Maximum results to return (default: unlimited) -
:validate(Boolean) - Validate found cabinets (default:true)
Returns: Array<Hash> - Array of found cabinets with metadata
Example:
results = Cabriolet::CAB::Decompressor.search('installer.exe')
results.each do |result|
puts "Found cabinet at offset #{result[:offset]}"
puts " Size: #{result[:size]} bytes"
puts " Files: #{result[:file_count]}"
end open(source, options = {}, &block)
Opens a cabinet with automatic resource management.
Parameters:
-
source- Same as constructor -
options- Same as constructor -
block- Block to execute with decompressor
Yields: Decompressor instance
Returns: Block return value
Example:
Cabriolet::CAB::Decompressor.open('archive.cab') do |decomp|
decomp.files.each do |file|
puts file.filename
end
end # Automatically closedCAB::Compressor
Constructor
new(options = {})
Creates a new CAB compressor instance.
Parameters:
-
options(Hash) - Configuration options
Options:
-
:compression(Symbol) - Default compression (:mszip,:lzx,:quantum,:none) -
:compression_level(Integer) - Compression level 1-21 for LZX (default:15) -
:set_id(Integer) - Cabinet set ID (default: random) -
:cabinet_id(Integer) - Cabinet ID within set (default:0) -
:max_cabinet_size(Integer) - Maximum cabinet size for splitting (default: unlimited)
Returns: New Compressor instance
Example:
# Default compression (MSZIP)
compressor = Cabriolet::CAB::Compressor.new
# With LZX compression
compressor = Cabriolet::CAB::Compressor.new(
compression: :lzx,
compression_level: 21
)
# For multi-part archives
compressor = Cabriolet::CAB::Compressor.new(
max_cabinet_size: 1_440_000 # 1.44 MB
)Instance Methods
add_file(path, options = {})
Adds a file to the cabinet.
Parameters:
-
path(String) - File path -
options(Hash) - File options
Options:
-
:compression(Symbol) - Override default compression -
:filename(String) - Archive filename (default: basename) -
:attributes(Integer) - File attributes -
:time(Time) - File modification time
Returns: self
Example:
compressor.add_file('readme.txt')
compressor.add_file('data.bin', compression: :lzx)
compressor.add_file('video.mp4', compression: :none) add_directory(path, options = {})
Recursively adds a directory.
Parameters:
-
path(String) - Directory path -
options(Hash) - Options
Options:
-
:compression(Symbol) - Compression for all files -
:exclude(Array, Regexp) - Patterns to exclude -
:recursive(Boolean) - Recurse subdirectories (default:true)
Returns: self
Example:
# Add entire directory
compressor.add_directory('mydata/')
# With exclusions
compressor.add_directory(
'project/',
exclude: ['.git', '*.log', /\.tmp$/]
) add_from_memory(filename, data, options = {})
Adds a file from memory.
Parameters:
-
filename(String) - Filename in archive -
data(String) - File contents -
options(Hash) - File options
Returns: self
Example:
# Add generated content
json_data = JSON.generate({key: 'value'})
compressor.add_from_memory('config.json', json_data)
# Add with custom time
compressor.add_from_memory(
'report.txt',
report_text,
time: Time.new(2024, 1, 1)
) add_folder(path, options = {})
Creates a new compression folder and adds files.
Parameters:
-
path(String) - Directory path -
options(Hash) - Folder options
Options:
-
:compression(Symbol) - Compression type for this folder
Returns: self
Example:
# Different compression for different content
compressor.add_folder('text_files/', compression: :quantum)
compressor.add_folder('binary_files/', compression: :lzx)
compressor.add_folder('media_files/', compression: :none) compress(output_path)
Compresses files to a cabinet.
Parameters:
-
output_path(String) - Output cabinet path
Returns: true on success
Raises: * Cabriolet::IOError - Write error * Cabriolet::CompressionError - Compression failed
Example:
compressor.add_directory('mydata/')
compressor.compress('output.cab')Thread Safety
Decompressor: * Constructor is thread-safe * Instance methods are not thread-safe * Use one instance per thread or add synchronization
Compressor: * Not thread-safe * Create separate instances for concurrent compression
Performance Notes
-
Buffer sizes affect performance significantly
-
LZX compression is slowest but best compression
-
MSZIP offers good balance of speed and compression
-
Memory operations are faster than disk I/O
-
Parallel extraction can improve throughput