Class: Omnizip::Formats::Msi::Reader

Inherits:
Object
  • Object
show all
Includes:
Constants
Defined in:
lib/omnizip/formats/msi/reader.rb

Overview

MSI Package Reader

Handles parsing and extraction of MSI packages. Uses OLE storage internally for reading embedded cabinets and resolving directory paths.

Constant Summary

Constants included from Constants

Constants::BINARY_TYPE, Constants::CATEGORY_BINARY, Constants::CATEGORY_CABINET, Constants::CATEGORY_CONDITION, Constants::CATEGORY_DEFAULT, Constants::CATEGORY_DOUBLE, Constants::CATEGORY_FILENAME, Constants::CATEGORY_GUID, Constants::CATEGORY_IDENTIFIER, Constants::CATEGORY_LANGUAGE, Constants::CATEGORY_LOWERCASE, Constants::CATEGORY_PATH, Constants::CATEGORY_SHORTCUT, Constants::CATEGORY_TEMPLATE, Constants::CATEGORY_TEXT, Constants::CATEGORY_UPPERCASE, Constants::CATEGORY_VERSION, Constants::COLUMNS_STREAM, Constants::COMPONENT_TABLE, Constants::COMP_ATTR_64BIT, Constants::COMP_ATTR_DISABLE_REGISTRY, Constants::COMP_ATTR_LOCAL_ONLY, Constants::COMP_ATTR_NEVER_OVERWRITE, Constants::COMP_ATTR_ODBC, Constants::COMP_ATTR_OPTIONAL, Constants::COMP_ATTR_PERMANENT, Constants::COMP_ATTR_REGISTRY_KEY_PATH, Constants::COMP_ATTR_SHARED, Constants::COMP_ATTR_SHARED_DLL, Constants::COMP_ATTR_SOURCE_ONLY, Constants::COMP_ATTR_TRANSITIVE, Constants::COMP_ATTR_UNINSTALL_ON_SUPERSEDE, Constants::DIRECTORY_TABLE, Constants::EMBEDDED_CAB_PREFIX, Constants::FILE_ATTR_CHECKSUM, Constants::FILE_ATTR_COMPRESSED, Constants::FILE_ATTR_HIDDEN, Constants::FILE_ATTR_NONCOMPRESSED, Constants::FILE_ATTR_PATCHADDED, Constants::FILE_ATTR_READONLY, Constants::FILE_ATTR_SYSTEM, Constants::FILE_ATTR_VITAL, Constants::FILE_TABLE, Constants::INT16_TYPE, Constants::INT32_TYPE, Constants::MEDIA_TABLE, Constants::OBJECT_TYPE, Constants::PROGRAM_FILES, Constants::PROGRAM_FILES_X64, Constants::SOURCE_DIR, Constants::STREAMS_TABLE, Constants::STRING_DATA_STREAM, Constants::STRING_POOL_STREAM, Constants::STRING_TYPE, Constants::SYSTEM_FOLDER, Constants::SYSTEM_X64_FOLDER, Constants::TABLES_STREAM, Constants::TARGET_DIR, Constants::WINDOWS_FOLDER

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Constants

decode_stream_name

Constructor Details

#initialize(path) ⇒ Reader

Initialize MSI package reader

Parameters:

  • path (String)

    Path to MSI file



45
46
47
48
49
# File 'lib/omnizip/formats/msi/reader.rb', line 45

def initialize(path)
  @path = path
  @entries = nil
  @component_dirs = {}
end

Instance Attribute Details

#cab_extractorCabExtractor (readonly)

Returns Cab extractor.

Returns:



31
32
33
# File 'lib/omnizip/formats/msi/reader.rb', line 31

def cab_extractor
  @cab_extractor
end

#component_dirsHash<String, String> (readonly)

Returns Component to directory mapping.

Returns:

  • (Hash<String, String>)

    Component to directory mapping



37
38
39
# File 'lib/omnizip/formats/msi/reader.rb', line 37

def component_dirs
  @component_dirs
end

#directory_resolverDirectoryResolver (readonly)

Returns Directory resolver.

Returns:



34
35
36
# File 'lib/omnizip/formats/msi/reader.rb', line 34

def directory_resolver
  @directory_resolver
end

#oleOle::Storage (readonly)

Returns OLE storage object.

Returns:



22
23
24
# File 'lib/omnizip/formats/msi/reader.rb', line 22

def ole
  @ole
end

#pathString (readonly)

Returns Path to MSI file.

Returns:

  • (String)

    Path to MSI file



19
20
21
# File 'lib/omnizip/formats/msi/reader.rb', line 19

def path
  @path
end

#string_poolStringPool (readonly)

Returns String pool for interned strings.

Returns:

  • (StringPool)

    String pool for interned strings



25
26
27
# File 'lib/omnizip/formats/msi/reader.rb', line 25

def string_pool
  @string_pool
end

#table_parserTableParser (readonly)

Returns Table parser.

Returns:



28
29
30
# File 'lib/omnizip/formats/msi/reader.rb', line 28

def table_parser
  @table_parser
end

Instance Method Details

#closeObject

Close MSI file



67
68
69
70
# File 'lib/omnizip/formats/msi/reader.rb', line 67

def close
  @ole&.close
  @ole = nil
end

#extract(output_dir) ⇒ Array<String>

Extract all files to output directory

Parameters:

  • output_dir (String)

    Output directory path

Returns:

  • (Array<String>)

    Extracted file paths



88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/omnizip/formats/msi/reader.rb', line 88

def extract(output_dir)
  FileUtils.mkdir_p(output_dir)

  # Extract files from cabinets
  cabinets = @cab_extractor.extract_cabinets
  extracted_files = extract_from_cabinets(cabinets, output_dir)

  # Clean up temp cabinet files
  cleanup_cabinets(cabinets)

  extracted_files
end

#filesArray<Entry> Also known as: entries

Get file entries from File table

Returns:

  • (Array<Entry>)

    File entries



75
76
77
# File 'lib/omnizip/formats/msi/reader.rb', line 75

def files
  @files ||= build_entries
end

#infoHash

Get information about MSI package

Returns:

  • (Hash)

    Package information



104
105
106
107
108
109
110
# File 'lib/omnizip/formats/msi/reader.rb', line 104

def info
  {
    path: @path,
    file_count: files.size,
    tables: @table_parser.table_names,
  }
end

#openReader

Open MSI file and parse tables

Returns:



54
55
56
57
58
59
60
61
62
63
64
# File 'lib/omnizip/formats/msi/reader.rb', line 54

def open
  @ole = Ole::Storage.open(@path)
  build_stream_name_map
  @string_pool = StringPool.new(@ole, method(:read_stream))
  @table_parser = TableParser.new(@string_pool, method(:read_stream))
  @directory_resolver = DirectoryResolver.new(@table_parser.table(DIRECTORY_TABLE))
  build_component_dirs
  @cab_extractor = CabExtractor.new(@ole,
                                    @table_parser.table(MEDIA_TABLE), @path, method(:read_stream))
  self
end