Class: Omnizip::Formats::Msi::CabExtractor
- Inherits:
-
Object
- Object
- Omnizip::Formats::Msi::CabExtractor
- Includes:
- Constants
- Defined in:
- lib/omnizip/formats/msi/cab_extractor.rb
Overview
MSI CAB Extractor
Handles extraction of files from embedded or external cabinet files. MSI packages can have cabinets embedded in the _Streams table or as separate .cab files alongside the MSI.
Constant Summary
Constants included from Constants
Omnizip::Formats::Msi::Constants::BINARY_TYPE, Omnizip::Formats::Msi::Constants::CATEGORY_BINARY, Omnizip::Formats::Msi::Constants::CATEGORY_CABINET, Omnizip::Formats::Msi::Constants::CATEGORY_CONDITION, Omnizip::Formats::Msi::Constants::CATEGORY_DEFAULT, Omnizip::Formats::Msi::Constants::CATEGORY_DOUBLE, Omnizip::Formats::Msi::Constants::CATEGORY_FILENAME, Omnizip::Formats::Msi::Constants::CATEGORY_GUID, Omnizip::Formats::Msi::Constants::CATEGORY_IDENTIFIER, Omnizip::Formats::Msi::Constants::CATEGORY_LANGUAGE, Omnizip::Formats::Msi::Constants::CATEGORY_LOWERCASE, Omnizip::Formats::Msi::Constants::CATEGORY_PATH, Omnizip::Formats::Msi::Constants::CATEGORY_SHORTCUT, Omnizip::Formats::Msi::Constants::CATEGORY_TEMPLATE, Omnizip::Formats::Msi::Constants::CATEGORY_TEXT, Omnizip::Formats::Msi::Constants::CATEGORY_UPPERCASE, Omnizip::Formats::Msi::Constants::CATEGORY_VERSION, Omnizip::Formats::Msi::Constants::COLUMNS_STREAM, Omnizip::Formats::Msi::Constants::COMPONENT_TABLE, Omnizip::Formats::Msi::Constants::COMP_ATTR_64BIT, Omnizip::Formats::Msi::Constants::COMP_ATTR_DISABLE_REGISTRY, Omnizip::Formats::Msi::Constants::COMP_ATTR_LOCAL_ONLY, Omnizip::Formats::Msi::Constants::COMP_ATTR_NEVER_OVERWRITE, Omnizip::Formats::Msi::Constants::COMP_ATTR_ODBC, Omnizip::Formats::Msi::Constants::COMP_ATTR_OPTIONAL, Omnizip::Formats::Msi::Constants::COMP_ATTR_PERMANENT, Omnizip::Formats::Msi::Constants::COMP_ATTR_REGISTRY_KEY_PATH, Omnizip::Formats::Msi::Constants::COMP_ATTR_SHARED, Omnizip::Formats::Msi::Constants::COMP_ATTR_SHARED_DLL, Omnizip::Formats::Msi::Constants::COMP_ATTR_SOURCE_ONLY, Omnizip::Formats::Msi::Constants::COMP_ATTR_TRANSITIVE, Omnizip::Formats::Msi::Constants::COMP_ATTR_UNINSTALL_ON_SUPERSEDE, Omnizip::Formats::Msi::Constants::DIRECTORY_TABLE, Omnizip::Formats::Msi::Constants::EMBEDDED_CAB_PREFIX, Omnizip::Formats::Msi::Constants::FILE_ATTR_CHECKSUM, Omnizip::Formats::Msi::Constants::FILE_ATTR_COMPRESSED, Omnizip::Formats::Msi::Constants::FILE_ATTR_HIDDEN, Omnizip::Formats::Msi::Constants::FILE_ATTR_NONCOMPRESSED, Omnizip::Formats::Msi::Constants::FILE_ATTR_PATCHADDED, Omnizip::Formats::Msi::Constants::FILE_ATTR_READONLY, Omnizip::Formats::Msi::Constants::FILE_ATTR_SYSTEM, Omnizip::Formats::Msi::Constants::FILE_ATTR_VITAL, Omnizip::Formats::Msi::Constants::FILE_TABLE, Omnizip::Formats::Msi::Constants::INT16_TYPE, Omnizip::Formats::Msi::Constants::INT32_TYPE, Omnizip::Formats::Msi::Constants::MEDIA_TABLE, Omnizip::Formats::Msi::Constants::OBJECT_TYPE, Omnizip::Formats::Msi::Constants::PROGRAM_FILES, Omnizip::Formats::Msi::Constants::PROGRAM_FILES_X64, Omnizip::Formats::Msi::Constants::SOURCE_DIR, Omnizip::Formats::Msi::Constants::STREAMS_TABLE, Omnizip::Formats::Msi::Constants::STRING_DATA_STREAM, Omnizip::Formats::Msi::Constants::STRING_POOL_STREAM, Omnizip::Formats::Msi::Constants::STRING_TYPE, Omnizip::Formats::Msi::Constants::SYSTEM_FOLDER, Omnizip::Formats::Msi::Constants::SYSTEM_X64_FOLDER, Omnizip::Formats::Msi::Constants::TABLES_STREAM, Omnizip::Formats::Msi::Constants::TARGET_DIR, Omnizip::Formats::Msi::Constants::WINDOWS_FOLDER
Instance Attribute Summary collapse
-
#media_table ⇒ Array<Hash>
readonly
Media table data.
-
#msi_path ⇒ String
readonly
Path to MSI file (for external CAB resolution).
-
#ole ⇒ Ole::Storage
readonly
OLE storage.
-
#read_stream ⇒ Proc
readonly
Stream reader method.
Instance Method Summary collapse
-
#extract_cabinets ⇒ Hash
Extract all cabinets to temporary files.
-
#find_cabinet_for_sequence(sequence, cabinets) ⇒ Hash?
Find the cabinet containing a file by sequence number.
-
#get_cabinet_data(cabinet_name) ⇒ String?
Get cabinet data for a media entry.
-
#initialize(ole, media_table, msi_path, stream_reader) ⇒ CabExtractor
constructor
Initialize CAB extractor.
Methods included from Constants
Constructor Details
#initialize(ole, media_table, msi_path, stream_reader) ⇒ CabExtractor
Initialize CAB extractor
35 36 37 38 39 40 |
# File 'lib/omnizip/formats/msi/cab_extractor.rb', line 35 def initialize(ole, media_table, msi_path, stream_reader) @ole = ole @media_table = media_table || [] @msi_path = msi_path @read_stream = stream_reader end |
Instance Attribute Details
#media_table ⇒ Array<Hash> (readonly)
Returns Media table data.
21 22 23 |
# File 'lib/omnizip/formats/msi/cab_extractor.rb', line 21 def media_table @media_table end |
#msi_path ⇒ String (readonly)
Returns Path to MSI file (for external CAB resolution).
24 25 26 |
# File 'lib/omnizip/formats/msi/cab_extractor.rb', line 24 def msi_path @msi_path end |
#ole ⇒ Ole::Storage (readonly)
Returns OLE storage.
18 19 20 |
# File 'lib/omnizip/formats/msi/cab_extractor.rb', line 18 def ole @ole end |
#read_stream ⇒ Proc (readonly)
Returns Stream reader method.
27 28 29 |
# File 'lib/omnizip/formats/msi/cab_extractor.rb', line 27 def read_stream @read_stream end |
Instance Method Details
#extract_cabinets ⇒ Hash
Extract all cabinets to temporary files
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 |
# File 'lib/omnizip/formats/msi/cab_extractor.rb', line 45 def extract_cabinets cabinets = {} @media_table.each do |media| cab_name = media["Cabinet"] next if cab_name.nil? || cab_name.empty? cab_data = get_cabinet_data(cab_name) next if cab_data.nil? || cab_data.empty? # Write to temp file temp_file = Tempfile.create(["msi_cab_", ".cab"]) temp_file.binmode temp_file.write(cab_data) temp_file.flush temp_file.close cabinets[media["DiskId"]] = { path: temp_file.path, name: cab_name, last_sequence: media["LastSequence"], temp_file: temp_file, } end cabinets end |
#find_cabinet_for_sequence(sequence, cabinets) ⇒ Hash?
Find the cabinet containing a file by sequence number
94 95 96 97 98 |
# File 'lib/omnizip/formats/msi/cab_extractor.rb', line 94 def find_cabinet_for_sequence(sequence, cabinets) # Sort by LastSequence and find the cabinet where sequence <= LastSequence sorted = cabinets.values.sort_by { |c| c[:last_sequence] } sorted.find { |c| sequence <= c[:last_sequence] } end |
#get_cabinet_data(cabinet_name) ⇒ String?
Get cabinet data for a media entry
77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/omnizip/formats/msi/cab_extractor.rb', line 77 def get_cabinet_data(cabinet_name) return nil if cabinet_name.nil? || cabinet_name.empty? if cabinet_name.start_with?(EMBEDDED_CAB_PREFIX) # Embedded cabinet (cabinet_name[1..]) else # External cabinet file read_external_cabinet(cabinet_name) end end |