omnizip 0.4.7-aarch64-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +32 -0
- data/.rubocop_todo.yml +293 -0
- data/CHANGELOG.md +1647 -0
- data/CONTEXT.md +68 -0
- data/COPYING +502 -0
- data/Gemfile +19 -0
- data/LICENSE +12 -0
- data/README.adoc +1327 -0
- data/Rakefile +15 -0
- data/TODO.refactor/00-overview.md +67 -0
- data/TODO.refactor/01-registry-base-class.md +81 -0
- data/TODO.refactor/02-error-hierarchy.md +57 -0
- data/TODO.refactor/03-autoload-entry-point.md +69 -0
- data/TODO.refactor/04-filter-base-consolidation.md +49 -0
- data/TODO.refactor/05-send-private-methods.md +64 -0
- data/TODO.refactor/06-instance-variable-access.md +69 -0
- data/TODO.refactor/07-respond-to-replacement.md +237 -0
- data/TODO.refactor/08-spec-doubles.md +27 -0
- data/TODO.refactor/09-cli-shared-module.md +35 -0
- data/TODO.refactor/10-format-detector-ocp.md +34 -0
- data/TODO.refactor/11-convenience-decoupling.md +38 -0
- data/TODO.refactor/12-thread-safety.md +8 -0
- data/TODO.refactor/13-lutaml-model-migration.md +158 -0
- data/TODO.refactor/14-add-missing-specs.md +25 -0
- data/benchmark/README.md +260 -0
- data/benchmark/benchmark_suite.rb +125 -0
- data/benchmark/compression_bench.rb +181 -0
- data/benchmark/filter_bench.rb +180 -0
- data/benchmark/models/benchmark_result.rb +59 -0
- data/benchmark/models/comparison_result.rb +69 -0
- data/benchmark/profile_suite.rb +167 -0
- data/benchmark/reporter.rb +150 -0
- data/benchmark/run_benchmarks.rb +66 -0
- data/benchmark/test_data.rb +137 -0
- data/config/formats/rar3_spec.yml +92 -0
- data/config/formats/rar5_spec.yml +102 -0
- data/docs/.github/workflows/docs.yml +142 -0
- data/docs/.gitignore +21 -0
- data/docs/.lychee.toml +67 -0
- data/docs/Gemfile +13 -0
- data/docs/RAR_WRITE_SUPPORT.md +26 -0
- data/docs/README.md +101 -0
- data/docs/_config.yml +112 -0
- data/docs/assets/logo.svg +1 -0
- data/docs/assets/omnizip-logo.pdf +1540 -11
- data/docs/comparison/feature-matrix.adoc +694 -0
- data/docs/comparison/index.adoc +113 -0
- data/docs/comparison/vs-7zip.adoc +309 -0
- data/docs/comparison/vs-peazip.adoc +77 -0
- data/docs/comparison/vs-rubyzip.adoc +342 -0
- data/docs/comparison/vs-winrar.adoc +100 -0
- data/docs/compatibility.adoc +579 -0
- data/docs/concepts/index.adoc +129 -0
- data/docs/developer/architecture.adoc +256 -0
- data/docs/developer/contributing.adoc +158 -0
- data/docs/developer/index.adoc +25 -0
- data/docs/developer/testing.adoc +212 -0
- data/docs/getting-started/basic-usage.adoc +263 -0
- data/docs/getting-started/index.adoc +42 -0
- data/docs/getting-started/installation.adoc +138 -0
- data/docs/getting-started/quick-start.adoc +183 -0
- data/docs/getting-started/your-first-archive.adoc +219 -0
- data/docs/guides/advanced-features/encryption.adoc +277 -0
- data/docs/guides/advanced-features/index.adoc +59 -0
- data/docs/guides/advanced-features/parallel-processing.adoc +144 -0
- data/docs/guides/advanced-features/progress-tracking.adoc +124 -0
- data/docs/guides/advanced-features/streaming.adoc +142 -0
- data/docs/guides/archive-formats/gzip-format.adoc +105 -0
- data/docs/guides/archive-formats/index.adoc +160 -0
- data/docs/guides/archive-formats/ole-format.adoc +151 -0
- data/docs/guides/archive-formats/rar-format.adoc +104 -0
- data/docs/guides/archive-formats/rar5.adoc +521 -0
- data/docs/guides/archive-formats/rpm-format.adoc +108 -0
- data/docs/guides/archive-formats/seven-zip-format.adoc +35 -0
- data/docs/guides/archive-formats/tar-format.adoc +106 -0
- data/docs/guides/archive-formats/xz-format.adoc +118 -0
- data/docs/guides/archive-formats/zip-format.adoc +35 -0
- data/docs/guides/compression-algorithms/bzip2.adoc +114 -0
- data/docs/guides/compression-algorithms/deflate.adoc +313 -0
- data/docs/guides/compression-algorithms/index.adoc +190 -0
- data/docs/guides/compression-algorithms/lzma.adoc +394 -0
- data/docs/guides/compression-algorithms/lzma2.adoc +244 -0
- data/docs/guides/compression-algorithms/ppmd.adoc +313 -0
- data/docs/guides/compression-algorithms/zstandard.adoc +296 -0
- data/docs/guides/creating-archives.adoc +348 -0
- data/docs/guides/extracting-archives.adoc +53 -0
- data/docs/guides/format-conversion.adoc +64 -0
- data/docs/guides/index.adoc +49 -0
- data/docs/guides/migration-rubyzip.adoc +217 -0
- data/docs/guides/parity-archives.adoc +605 -0
- data/docs/guides/performance-tuning.adoc +88 -0
- data/docs/index.adoc +228 -0
- data/docs/lychee.toml +67 -0
- data/docs/reference/api/overview.adoc +187 -0
- data/docs/reference/cli/compress-command.adoc +114 -0
- data/docs/reference/cli/overview.adoc +140 -0
- data/docs/reference/index.adoc +26 -0
- data/docs/resources/faq.adoc +185 -0
- data/docs/resources/quick-reference.adoc +222 -0
- data/docs/rust-backend.md +0 -0
- data/docs/troubleshooting/index.adoc +207 -0
- data/docs/xar_format.md +216 -0
- data/examples/api_comparison.rb +205 -0
- data/examples/deflate64_example.rb +96 -0
- data/examples/par2_demo.rb +121 -0
- data/examples/quick_start_native.rb +150 -0
- data/examples/quick_start_rubyzip.rb +115 -0
- data/examples/rubyzip_compatibility_demo.rb +194 -0
- data/exe/omnizip +27 -0
- data/lib/omnizip/algorithm.rb +176 -0
- data/lib/omnizip/algorithm_registry.rb +65 -0
- data/lib/omnizip/algorithms/.keep +0 -0
- data/lib/omnizip/algorithms/bzip2/bwt.rb +236 -0
- data/lib/omnizip/algorithms/bzip2/bz2.rb +687 -0
- data/lib/omnizip/algorithms/bzip2/rle.rb +146 -0
- data/lib/omnizip/algorithms/bzip2.rb +108 -0
- data/lib/omnizip/algorithms/deflate/constants.rb +28 -0
- data/lib/omnizip/algorithms/deflate/decoder.rb +37 -0
- data/lib/omnizip/algorithms/deflate/encoder.rb +45 -0
- data/lib/omnizip/algorithms/deflate.rb +135 -0
- data/lib/omnizip/algorithms/deflate64/constants.rb +45 -0
- data/lib/omnizip/algorithms/deflate64/decoder.rb +151 -0
- data/lib/omnizip/algorithms/deflate64/encoder.rb +95 -0
- data/lib/omnizip/algorithms/deflate64/huffman_coder.rb +352 -0
- data/lib/omnizip/algorithms/deflate64/lz77_encoder.rb +140 -0
- data/lib/omnizip/algorithms/deflate64.rb +118 -0
- data/lib/omnizip/algorithms/lzma/bit_model.rb +120 -0
- data/lib/omnizip/algorithms/lzma/constants.rb +112 -0
- data/lib/omnizip/algorithms/lzma/decoder.rb +146 -0
- data/lib/omnizip/algorithms/lzma/dictionary.rb +70 -0
- data/lib/omnizip/algorithms/lzma/distance_coder.rb +326 -0
- data/lib/omnizip/algorithms/lzma/encoder.rb +139 -0
- data/lib/omnizip/algorithms/lzma/length_coder.rb +172 -0
- data/lib/omnizip/algorithms/lzma/literal_decoder.rb +204 -0
- data/lib/omnizip/algorithms/lzma/literal_encoder.rb +208 -0
- data/lib/omnizip/algorithms/lzma/lzip_decoder.rb +368 -0
- data/lib/omnizip/algorithms/lzma/lzma1_encoder.rb +105 -0
- data/lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb +194 -0
- data/lib/omnizip/algorithms/lzma/lzma_state.rb +128 -0
- data/lib/omnizip/algorithms/lzma/match.rb +32 -0
- data/lib/omnizip/algorithms/lzma/match_finder.rb +233 -0
- data/lib/omnizip/algorithms/lzma/match_finder_config.rb +142 -0
- data/lib/omnizip/algorithms/lzma/match_finder_factory.rb +84 -0
- data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +159 -0
- data/lib/omnizip/algorithms/lzma/probability_models.rb +72 -0
- data/lib/omnizip/algorithms/lzma/range_coder.rb +82 -0
- data/lib/omnizip/algorithms/lzma/range_decoder.rb +274 -0
- data/lib/omnizip/algorithms/lzma/range_encoder.rb +202 -0
- data/lib/omnizip/algorithms/lzma/state.rb +127 -0
- data/lib/omnizip/algorithms/lzma/xz_buffered_range_encoder.rb +323 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder.rb +420 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder_fast.rb +640 -0
- data/lib/omnizip/algorithms/lzma/xz_match_finder_adapter.rb +224 -0
- data/lib/omnizip/algorithms/lzma/xz_price_calculator.rb +167 -0
- data/lib/omnizip/algorithms/lzma/xz_probability_models.rb +258 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder.rb +223 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder_exact.rb +314 -0
- data/lib/omnizip/algorithms/lzma/xz_state.rb +108 -0
- data/lib/omnizip/algorithms/lzma/xz_utils_decoder.rb +1311 -0
- data/lib/omnizip/algorithms/lzma.rb +266 -0
- data/lib/omnizip/algorithms/lzma2/chunk_manager.rb +180 -0
- data/lib/omnizip/algorithms/lzma2/constants.rb +38 -0
- data/lib/omnizip/algorithms/lzma2/encoder.rb +145 -0
- data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +165 -0
- data/lib/omnizip/algorithms/lzma2/properties.rb +179 -0
- data/lib/omnizip/algorithms/lzma2/simple_lzma2_encoder.rb +122 -0
- data/lib/omnizip/algorithms/lzma2/xz_encoder_adapter.rb +85 -0
- data/lib/omnizip/algorithms/lzma2.rb +133 -0
- data/lib/omnizip/algorithms/ppmd7/constants.rb +74 -0
- data/lib/omnizip/algorithms/ppmd7/context.rb +151 -0
- data/lib/omnizip/algorithms/ppmd7/decoder.rb +127 -0
- data/lib/omnizip/algorithms/ppmd7/encoder.rb +153 -0
- data/lib/omnizip/algorithms/ppmd7/model.rb +245 -0
- data/lib/omnizip/algorithms/ppmd7/symbol_state.rb +57 -0
- data/lib/omnizip/algorithms/ppmd7.rb +146 -0
- data/lib/omnizip/algorithms/ppmd8/constants.rb +61 -0
- data/lib/omnizip/algorithms/ppmd8/context.rb +32 -0
- data/lib/omnizip/algorithms/ppmd8/decoder.rb +104 -0
- data/lib/omnizip/algorithms/ppmd8/encoder.rb +135 -0
- data/lib/omnizip/algorithms/ppmd8/model.rb +246 -0
- data/lib/omnizip/algorithms/ppmd8/restoration_method.rb +78 -0
- data/lib/omnizip/algorithms/ppmd8.rb +122 -0
- data/lib/omnizip/algorithms/ppmd_base.rb +142 -0
- data/lib/omnizip/algorithms/registration.rb +28 -0
- data/lib/omnizip/algorithms/zstandard/constants.rb +158 -0
- data/lib/omnizip/algorithms/zstandard/decoder.rb +249 -0
- data/lib/omnizip/algorithms/zstandard/dictionary.rb +73 -0
- data/lib/omnizip/algorithms/zstandard/encoder.rb +294 -0
- data/lib/omnizip/algorithms/zstandard/frame/block.rb +143 -0
- data/lib/omnizip/algorithms/zstandard/frame/header.rb +233 -0
- data/lib/omnizip/algorithms/zstandard/frame.rb +33 -0
- data/lib/omnizip/algorithms/zstandard/fse/bitstream.rb +183 -0
- data/lib/omnizip/algorithms/zstandard/fse/encoder.rb +534 -0
- data/lib/omnizip/algorithms/zstandard/fse/interleaved.rb +92 -0
- data/lib/omnizip/algorithms/zstandard/fse/table.rb +188 -0
- data/lib/omnizip/algorithms/zstandard/fse/table_description.rb +203 -0
- data/lib/omnizip/algorithms/zstandard/fse.rb +53 -0
- data/lib/omnizip/algorithms/zstandard/huffman.rb +276 -0
- data/lib/omnizip/algorithms/zstandard/huffman_encoder.rb +327 -0
- data/lib/omnizip/algorithms/zstandard/ldm.rb +121 -0
- data/lib/omnizip/algorithms/zstandard/literals.rb +241 -0
- data/lib/omnizip/algorithms/zstandard/literals_encoder.rb +96 -0
- data/lib/omnizip/algorithms/zstandard/match_finder.rb +483 -0
- data/lib/omnizip/algorithms/zstandard/sequences.rb +350 -0
- data/lib/omnizip/algorithms/zstandard/sequences_encoder.rb +333 -0
- data/lib/omnizip/algorithms/zstandard/xxhash.rb +159 -0
- data/lib/omnizip/algorithms/zstandard.rb +210 -0
- data/lib/omnizip/algorithms.rb +35 -0
- data/lib/omnizip/archive/builder.rb +48 -0
- data/lib/omnizip/archive/reader_session.rb +67 -0
- data/lib/omnizip/archive.rb +86 -0
- data/lib/omnizip/archive_handler.rb +82 -0
- data/lib/omnizip/archive_handlers/cpio_handler.rb +47 -0
- data/lib/omnizip/archive_handlers/iso_handler.rb +54 -0
- data/lib/omnizip/archive_handlers/ole_handler.rb +37 -0
- data/lib/omnizip/archive_handlers/rar_handler.rb +96 -0
- data/lib/omnizip/archive_handlers/rpm_handler.rb +45 -0
- data/lib/omnizip/archive_handlers/seven_zip_handler.rb +89 -0
- data/lib/omnizip/archive_handlers/tar_handler.rb +75 -0
- data/lib/omnizip/archive_handlers/xar_handler.rb +49 -0
- data/lib/omnizip/archive_handlers/zip_handler.rb +115 -0
- data/lib/omnizip/archive_handlers.rb +18 -0
- data/lib/omnizip/backends.rb +160 -0
- data/lib/omnizip/buffer/memory_archive.rb +246 -0
- data/lib/omnizip/buffer/memory_extractor.rb +234 -0
- data/lib/omnizip/buffer/seven_zip_bridge.rb +171 -0
- data/lib/omnizip/buffer.rb +187 -0
- data/lib/omnizip/checksum_registry.rb +41 -0
- data/lib/omnizip/checksums/crc32.rb +101 -0
- data/lib/omnizip/checksums/crc64.rb +102 -0
- data/lib/omnizip/checksums/crc_base.rb +158 -0
- data/lib/omnizip/checksums/registration.rb +16 -0
- data/lib/omnizip/checksums/verifier.rb +130 -0
- data/lib/omnizip/checksums.rb +11 -0
- data/lib/omnizip/chunked/memory_manager.rb +194 -0
- data/lib/omnizip/chunked/reader.rb +78 -0
- data/lib/omnizip/chunked/writer.rb +123 -0
- data/lib/omnizip/chunked.rb +123 -0
- data/lib/omnizip/cli/output_formatter.rb +112 -0
- data/lib/omnizip/cli.rb +604 -0
- data/lib/omnizip/commands/.keep +0 -0
- data/lib/omnizip/commands/archive_create_command.rb +245 -0
- data/lib/omnizip/commands/archive_extract_command.rb +231 -0
- data/lib/omnizip/commands/archive_list_command.rb +204 -0
- data/lib/omnizip/commands/archive_repair_command.rb +129 -0
- data/lib/omnizip/commands/archive_verify_command.rb +115 -0
- data/lib/omnizip/commands/compress_command.rb +115 -0
- data/lib/omnizip/commands/decompress_command.rb +149 -0
- data/lib/omnizip/commands/list_command.rb +51 -0
- data/lib/omnizip/commands/metadata_command.rb +215 -0
- data/lib/omnizip/commands/parity_create_command.rb +114 -0
- data/lib/omnizip/commands/parity_repair_command.rb +120 -0
- data/lib/omnizip/commands/parity_verify_command.rb +122 -0
- data/lib/omnizip/commands/profile_list_command.rb +54 -0
- data/lib/omnizip/commands/profile_show_command.rb +44 -0
- data/lib/omnizip/commands.rb +21 -0
- data/lib/omnizip/convenience.rb +389 -0
- data/lib/omnizip/converter/conversion_registry.rb +50 -0
- data/lib/omnizip/converter/conversion_strategy.rb +108 -0
- data/lib/omnizip/converter/extract_repack_strategy.rb +51 -0
- data/lib/omnizip/converter/seven_zip_to_zip_strategy.rb +43 -0
- data/lib/omnizip/converter/zip_to_seven_zip_strategy.rb +54 -0
- data/lib/omnizip/converter.rb +124 -0
- data/lib/omnizip/crypto/aes256/cipher.rb +104 -0
- data/lib/omnizip/crypto/aes256/constants.rb +28 -0
- data/lib/omnizip/crypto/aes256/key_derivation.rb +100 -0
- data/lib/omnizip/crypto/aes256.rb +102 -0
- data/lib/omnizip/crypto.rb +11 -0
- data/lib/omnizip/entry.rb +44 -0
- data/lib/omnizip/error.rb +110 -0
- data/lib/omnizip/eta/exponential_smoothing_estimator.rb +95 -0
- data/lib/omnizip/eta/moving_average_estimator.rb +96 -0
- data/lib/omnizip/eta/rate_calculator.rb +104 -0
- data/lib/omnizip/eta/sample_history.rb +143 -0
- data/lib/omnizip/eta/time_estimator.rb +106 -0
- data/lib/omnizip/eta.rb +68 -0
- data/lib/omnizip/extraction/filter_chain.rb +179 -0
- data/lib/omnizip/extraction/glob_pattern.rb +140 -0
- data/lib/omnizip/extraction/pattern_matcher.rb +66 -0
- data/lib/omnizip/extraction/predicate_pattern.rb +52 -0
- data/lib/omnizip/extraction/regex_pattern.rb +50 -0
- data/lib/omnizip/extraction/selective_extractor.rb +247 -0
- data/lib/omnizip/extraction.rb +115 -0
- data/lib/omnizip/file_type/mime_classifier.rb +144 -0
- data/lib/omnizip/file_type.rb +117 -0
- data/lib/omnizip/filter.rb +141 -0
- data/lib/omnizip/filter_pipeline.rb +108 -0
- data/lib/omnizip/filter_registry.rb +113 -0
- data/lib/omnizip/filters/bcj.rb +277 -0
- data/lib/omnizip/filters/bcj2/constants.rb +53 -0
- data/lib/omnizip/filters/bcj2/decoder.rb +263 -0
- data/lib/omnizip/filters/bcj2/encoder.rb +58 -0
- data/lib/omnizip/filters/bcj2/stream_data.rb +91 -0
- data/lib/omnizip/filters/bcj2.rb +93 -0
- data/lib/omnizip/filters/bcj_arm.rb +174 -0
- data/lib/omnizip/filters/bcj_arm64.rb +242 -0
- data/lib/omnizip/filters/bcj_ia64.rb +194 -0
- data/lib/omnizip/filters/bcj_ppc.rb +188 -0
- data/lib/omnizip/filters/bcj_sparc.rb +174 -0
- data/lib/omnizip/filters/bcj_x86.rb +191 -0
- data/lib/omnizip/filters/delta.rb +195 -0
- data/lib/omnizip/filters/xz_delta.rb +258 -0
- data/lib/omnizip/filters.rb +20 -0
- data/lib/omnizip/format_detector.rb +166 -0
- data/lib/omnizip/formats/.keep +0 -0
- data/lib/omnizip/formats/bzip2_file.rb +159 -0
- data/lib/omnizip/formats/cpio/bounded_io.rb +66 -0
- data/lib/omnizip/formats/cpio/constants.rb +55 -0
- data/lib/omnizip/formats/cpio/entry.rb +389 -0
- data/lib/omnizip/formats/cpio/reader.rb +194 -0
- data/lib/omnizip/formats/cpio/writer.rb +232 -0
- data/lib/omnizip/formats/cpio.rb +132 -0
- data/lib/omnizip/formats/format_spec_loader.rb +228 -0
- data/lib/omnizip/formats/gzip.rb +236 -0
- data/lib/omnizip/formats/iso/directory_builder.rb +321 -0
- data/lib/omnizip/formats/iso/directory_record.rb +162 -0
- data/lib/omnizip/formats/iso/joliet.rb +204 -0
- data/lib/omnizip/formats/iso/path_table.rb +125 -0
- data/lib/omnizip/formats/iso/reader.rb +194 -0
- data/lib/omnizip/formats/iso/rock_ridge.rb +349 -0
- data/lib/omnizip/formats/iso/volume_builder.rb +319 -0
- data/lib/omnizip/formats/iso/volume_descriptor.rb +168 -0
- data/lib/omnizip/formats/iso/writer.rb +543 -0
- data/lib/omnizip/formats/iso.rb +133 -0
- data/lib/omnizip/formats/lzip.rb +161 -0
- data/lib/omnizip/formats/lzma_alone.rb +149 -0
- data/lib/omnizip/formats/msi/cab_extractor.rb +181 -0
- data/lib/omnizip/formats/msi/constants.rb +157 -0
- data/lib/omnizip/formats/msi/directory_resolver.rb +188 -0
- data/lib/omnizip/formats/msi/entry.rb +134 -0
- data/lib/omnizip/formats/msi/reader.rb +301 -0
- data/lib/omnizip/formats/msi/string_pool.rb +246 -0
- data/lib/omnizip/formats/msi/table_parser.rb +244 -0
- data/lib/omnizip/formats/msi.rb +73 -0
- data/lib/omnizip/formats/ole/allocation_table.rb +263 -0
- data/lib/omnizip/formats/ole/constants.rb +61 -0
- data/lib/omnizip/formats/ole/dirent.rb +439 -0
- data/lib/omnizip/formats/ole/header.rb +199 -0
- data/lib/omnizip/formats/ole/ranges_io.rb +347 -0
- data/lib/omnizip/formats/ole/storage.rb +482 -0
- data/lib/omnizip/formats/ole/types/variant.rb +338 -0
- data/lib/omnizip/formats/ole.rb +143 -0
- data/lib/omnizip/formats/rar/archive_repairer.rb +240 -0
- data/lib/omnizip/formats/rar/archive_verifier.rb +192 -0
- data/lib/omnizip/formats/rar/block_parser.rb +282 -0
- data/lib/omnizip/formats/rar/compression/bit_stream.rb +180 -0
- data/lib/omnizip/formats/rar/compression/dispatcher.rb +210 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/decoder.rb +212 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/encoder.rb +154 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_builder.rb +217 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_coder.rb +189 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/match_finder.rb +135 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/sliding_window.rb +165 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman.rb +25 -0
- data/lib/omnizip/formats/rar/compression/ppmd/context.rb +103 -0
- data/lib/omnizip/formats/rar/compression/ppmd/decoder.rb +238 -0
- data/lib/omnizip/formats/rar/compression/ppmd/encoder.rb +250 -0
- data/lib/omnizip/formats/rar/compression/ppmd.rb +16 -0
- data/lib/omnizip/formats/rar/compression.rb +17 -0
- data/lib/omnizip/formats/rar/compression_method_registry.rb +106 -0
- data/lib/omnizip/formats/rar/constants.rb +88 -0
- data/lib/omnizip/formats/rar/decompressor.rb +316 -0
- data/lib/omnizip/formats/rar/external_writer.rb +311 -0
- data/lib/omnizip/formats/rar/header.rb +209 -0
- data/lib/omnizip/formats/rar/license_validator.rb +111 -0
- data/lib/omnizip/formats/rar/models/rar_archive.rb +77 -0
- data/lib/omnizip/formats/rar/models/rar_entry.rb +65 -0
- data/lib/omnizip/formats/rar/models/rar_volume.rb +56 -0
- data/lib/omnizip/formats/rar/models.rb +14 -0
- data/lib/omnizip/formats/rar/parity_handler.rb +299 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzma.rb +200 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzss.rb +584 -0
- data/lib/omnizip/formats/rar/rar5/compression/store.rb +60 -0
- data/lib/omnizip/formats/rar/rar5/crc32.rb +39 -0
- data/lib/omnizip/formats/rar/rar5/encryption/aes256_cbc.rb +96 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_header.rb +114 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_manager.rb +162 -0
- data/lib/omnizip/formats/rar/rar5/encryption/key_derivation.rb +97 -0
- data/lib/omnizip/formats/rar/rar5/header.rb +208 -0
- data/lib/omnizip/formats/rar/rar5/models/encryption_options.rb +74 -0
- data/lib/omnizip/formats/rar/rar5/models/recovery_options.rb +63 -0
- data/lib/omnizip/formats/rar/rar5/models/solid_options.rb +63 -0
- data/lib/omnizip/formats/rar/rar5/models/volume_options.rb +74 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/ARCHITECTURE.md +290 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_manager.rb +260 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_splitter.rb +155 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb +176 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_encoder.rb +108 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_manager.rb +139 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_stream.rb +121 -0
- data/lib/omnizip/formats/rar/rar5/vint.rb +53 -0
- data/lib/omnizip/formats/rar/rar5/writer.rb +540 -0
- data/lib/omnizip/formats/rar/rar_format_base.rb +239 -0
- data/lib/omnizip/formats/rar/reader.rb +377 -0
- data/lib/omnizip/formats/rar/recovery_record.rb +245 -0
- data/lib/omnizip/formats/rar/volume_manager.rb +166 -0
- data/lib/omnizip/formats/rar/writer.rb +437 -0
- data/lib/omnizip/formats/rar.rb +193 -0
- data/lib/omnizip/formats/rar3/compressor.rb +71 -0
- data/lib/omnizip/formats/rar3/decompressor.rb +64 -0
- data/lib/omnizip/formats/rar3/reader.rb +107 -0
- data/lib/omnizip/formats/rar3/writer.rb +220 -0
- data/lib/omnizip/formats/rar3.rb +15 -0
- data/lib/omnizip/formats/rar5/compressor.rb +71 -0
- data/lib/omnizip/formats/rar5/decompressor.rb +64 -0
- data/lib/omnizip/formats/rar5/reader.rb +130 -0
- data/lib/omnizip/formats/rar5/writer.rb +65 -0
- data/lib/omnizip/formats/rar5.rb +15 -0
- data/lib/omnizip/formats/rpm/constants.rb +58 -0
- data/lib/omnizip/formats/rpm/entry.rb +106 -0
- data/lib/omnizip/formats/rpm/header.rb +106 -0
- data/lib/omnizip/formats/rpm/lead.rb +132 -0
- data/lib/omnizip/formats/rpm/tag.rb +228 -0
- data/lib/omnizip/formats/rpm/writer.rb +652 -0
- data/lib/omnizip/formats/rpm.rb +458 -0
- data/lib/omnizip/formats/seven_zip/bcj2_stream_decompressor.rb +274 -0
- data/lib/omnizip/formats/seven_zip/coder_chain.rb +169 -0
- data/lib/omnizip/formats/seven_zip/constants.rb +126 -0
- data/lib/omnizip/formats/seven_zip/encoded_header.rb +110 -0
- data/lib/omnizip/formats/seven_zip/encrypted_header.rb +139 -0
- data/lib/omnizip/formats/seven_zip/file_collector.rb +143 -0
- data/lib/omnizip/formats/seven_zip/header.rb +102 -0
- data/lib/omnizip/formats/seven_zip/header_encryptor.rb +132 -0
- data/lib/omnizip/formats/seven_zip/header_writer.rb +425 -0
- data/lib/omnizip/formats/seven_zip/models/coder_info.rb +30 -0
- data/lib/omnizip/formats/seven_zip/models/file_entry.rb +65 -0
- data/lib/omnizip/formats/seven_zip/models/folder.rb +67 -0
- data/lib/omnizip/formats/seven_zip/models/stream_info.rb +42 -0
- data/lib/omnizip/formats/seven_zip/models.rb +20 -0
- data/lib/omnizip/formats/seven_zip/parser.rb +671 -0
- data/lib/omnizip/formats/seven_zip/reader.rb +626 -0
- data/lib/omnizip/formats/seven_zip/split_archive_reader.rb +611 -0
- data/lib/omnizip/formats/seven_zip/split_archive_writer.rb +308 -0
- data/lib/omnizip/formats/seven_zip/stream_compressor.rb +151 -0
- data/lib/omnizip/formats/seven_zip/stream_decompressor.rb +166 -0
- data/lib/omnizip/formats/seven_zip/writer.rb +801 -0
- data/lib/omnizip/formats/seven_zip.rb +179 -0
- data/lib/omnizip/formats/tar/constants.rb +73 -0
- data/lib/omnizip/formats/tar/entry.rb +98 -0
- data/lib/omnizip/formats/tar/header.rb +206 -0
- data/lib/omnizip/formats/tar/reader.rb +119 -0
- data/lib/omnizip/formats/tar/writer.rb +212 -0
- data/lib/omnizip/formats/tar.rb +74 -0
- data/lib/omnizip/formats/xar/constants.rb +119 -0
- data/lib/omnizip/formats/xar/entry.rb +268 -0
- data/lib/omnizip/formats/xar/header.rb +223 -0
- data/lib/omnizip/formats/xar/reader.rb +400 -0
- data/lib/omnizip/formats/xar/toc.rb +570 -0
- data/lib/omnizip/formats/xar/writer.rb +461 -0
- data/lib/omnizip/formats/xar.rb +145 -0
- data/lib/omnizip/formats/xz/reader.rb +121 -0
- data/lib/omnizip/formats/xz/writer.rb +416 -0
- data/lib/omnizip/formats/xz.rb +210 -0
- data/lib/omnizip/formats/xz_const.rb +49 -0
- data/lib/omnizip/formats/xz_impl/block_decoder.rb +761 -0
- data/lib/omnizip/formats/xz_impl/block_encoder.rb +304 -0
- data/lib/omnizip/formats/xz_impl/block_header.rb +210 -0
- data/lib/omnizip/formats/xz_impl/block_header_parser.rb +182 -0
- data/lib/omnizip/formats/xz_impl/index_decoder.rb +174 -0
- data/lib/omnizip/formats/xz_impl/index_encoder.rb +120 -0
- data/lib/omnizip/formats/xz_impl/stream_decoder.rb +470 -0
- data/lib/omnizip/formats/xz_impl/stream_encoder.rb +95 -0
- data/lib/omnizip/formats/xz_impl/stream_footer.rb +79 -0
- data/lib/omnizip/formats/xz_impl/stream_footer_parser.rb +115 -0
- data/lib/omnizip/formats/xz_impl/stream_header.rb +53 -0
- data/lib/omnizip/formats/xz_impl/stream_header_parser.rb +106 -0
- data/lib/omnizip/formats/xz_impl/vli.rb +128 -0
- data/lib/omnizip/formats/xz_impl.rb +52 -0
- data/lib/omnizip/formats/zip/central_directory_header.rb +223 -0
- data/lib/omnizip/formats/zip/constants.rb +69 -0
- data/lib/omnizip/formats/zip/end_of_central_directory.rb +132 -0
- data/lib/omnizip/formats/zip/local_file_header.rb +136 -0
- data/lib/omnizip/formats/zip/reader.rb +376 -0
- data/lib/omnizip/formats/zip/unix_extra_field.rb +153 -0
- data/lib/omnizip/formats/zip/writer.rb +489 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory.rb +102 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory_locator.rb +64 -0
- data/lib/omnizip/formats/zip/zip64_extra_field.rb +112 -0
- data/lib/omnizip/formats/zip.rb +50 -0
- data/lib/omnizip/formats.rb +29 -0
- data/lib/omnizip/implementations/base/lzma2_decoder_base.rb +75 -0
- data/lib/omnizip/implementations/base/lzma2_encoder_base.rb +128 -0
- data/lib/omnizip/implementations/base/lzma_decoder_base.rb +83 -0
- data/lib/omnizip/implementations/base/lzma_encoder_base.rb +108 -0
- data/lib/omnizip/implementations/base/state_machine_base.rb +182 -0
- data/lib/omnizip/implementations/base.rb +19 -0
- data/lib/omnizip/implementations/rust/archive.rb +93 -0
- data/lib/omnizip/implementations/rust/library.rb +221 -0
- data/lib/omnizip/implementations/rust.rb +26 -0
- data/lib/omnizip/implementations/seven_zip/lzma/decoder.rb +428 -0
- data/lib/omnizip/implementations/seven_zip/lzma/encoder.rb +456 -0
- data/lib/omnizip/implementations/seven_zip/lzma/match_finder.rb +285 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb +197 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_encoder.rb +194 -0
- data/lib/omnizip/implementations/seven_zip/lzma/state_machine.rb +139 -0
- data/lib/omnizip/implementations/seven_zip/lzma.rb +21 -0
- data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +56 -0
- data/lib/omnizip/implementations/seven_zip/lzma2.rb +12 -0
- data/lib/omnizip/implementations/seven_zip.rb +11 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/decoder.rb +547 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +748 -0
- data/lib/omnizip/implementations/xz_utils/lzma2.rb +13 -0
- data/lib/omnizip/implementations/xz_utils.rb +10 -0
- data/lib/omnizip/implementations.rb +25 -0
- data/lib/omnizip/io/buffered_input.rb +147 -0
- data/lib/omnizip/io/buffered_output.rb +106 -0
- data/lib/omnizip/io/source.rb +143 -0
- data/lib/omnizip/io/stream_manager.rb +117 -0
- data/lib/omnizip/io.rb +15 -0
- data/lib/omnizip/link_handler/hard_link.rb +79 -0
- data/lib/omnizip/link_handler/symbolic_link.rb +74 -0
- data/lib/omnizip/link_handler.rb +129 -0
- data/lib/omnizip/metadata/archive_metadata.rb +114 -0
- data/lib/omnizip/metadata/entry_metadata.rb +153 -0
- data/lib/omnizip/metadata/metadata_editor.rb +169 -0
- data/lib/omnizip/metadata/metadata_registry.rb +71 -0
- data/lib/omnizip/metadata/metadata_validator.rb +101 -0
- data/lib/omnizip/metadata.rb +58 -0
- data/lib/omnizip/models/.keep +0 -0
- data/lib/omnizip/models/algorithm_metadata.rb +41 -0
- data/lib/omnizip/models/attribute_apply.rb +40 -0
- data/lib/omnizip/models/compression_options.rb +53 -0
- data/lib/omnizip/models/conversion_options.rb +79 -0
- data/lib/omnizip/models/conversion_result.rb +141 -0
- data/lib/omnizip/models/eta_result.rb +45 -0
- data/lib/omnizip/models/extraction_rule.rb +115 -0
- data/lib/omnizip/models/filter_chain.rb +142 -0
- data/lib/omnizip/models/filter_config.rb +148 -0
- data/lib/omnizip/models/match_result.rb +141 -0
- data/lib/omnizip/models/optimization_suggestion.rb +95 -0
- data/lib/omnizip/models/parallel_options.rb +116 -0
- data/lib/omnizip/models/performance_result.rb +85 -0
- data/lib/omnizip/models/profile_report.rb +116 -0
- data/lib/omnizip/models/progress_options.rb +39 -0
- data/lib/omnizip/models/split_options.rb +116 -0
- data/lib/omnizip/optimization_registry.rb +45 -0
- data/lib/omnizip/parallel/engine.rb +52 -0
- data/lib/omnizip/parallel/job_queue.rb +209 -0
- data/lib/omnizip/parallel/job_scheduler.rb +225 -0
- data/lib/omnizip/parallel/parallel_compressor.rb +326 -0
- data/lib/omnizip/parallel/parallel_extractor.rb +238 -0
- data/lib/omnizip/parallel/thread_pool.rb +60 -0
- data/lib/omnizip/parallel/worker_pool.rb +227 -0
- data/lib/omnizip/parallel.rb +156 -0
- data/lib/omnizip/parity/chunked_block_processor.rb +194 -0
- data/lib/omnizip/parity/galois16.rb +145 -0
- data/lib/omnizip/parity/models/creator_packet.rb +71 -0
- data/lib/omnizip/parity/models/file_description_packet.rb +131 -0
- data/lib/omnizip/parity/models/ifsc_packet.rb +111 -0
- data/lib/omnizip/parity/models/main_packet.rb +126 -0
- data/lib/omnizip/parity/models/packet.rb +156 -0
- data/lib/omnizip/parity/models/packet_registry.rb +102 -0
- data/lib/omnizip/parity/models/recovery_slice_packet.rb +76 -0
- data/lib/omnizip/parity/models.rb +27 -0
- data/lib/omnizip/parity/par2_creator.rb +496 -0
- data/lib/omnizip/parity/par2_repairer.rb +409 -0
- data/lib/omnizip/parity/par2_verifier.rb +373 -0
- data/lib/omnizip/parity/par2cmdline_algorithm.rb +108 -0
- data/lib/omnizip/parity/par2cmdline_coefficients.rb +78 -0
- data/lib/omnizip/parity/reed_solomon_decoder.rb +263 -0
- data/lib/omnizip/parity/reed_solomon_encoder.rb +108 -0
- data/lib/omnizip/parity/reed_solomon_matrix.rb +339 -0
- data/lib/omnizip/parity.rb +207 -0
- data/lib/omnizip/password/encryption_registry.rb +26 -0
- data/lib/omnizip/password/encryption_strategy.rb +96 -0
- data/lib/omnizip/password/password_validator.rb +129 -0
- data/lib/omnizip/password/winzip_aes_strategy.rb +190 -0
- data/lib/omnizip/password/zip_crypto_strategy.rb +135 -0
- data/lib/omnizip/password.rb +88 -0
- data/lib/omnizip/pipe/stream_compressor.rb +124 -0
- data/lib/omnizip/pipe/stream_decompressor.rb +173 -0
- data/lib/omnizip/pipe.rb +120 -0
- data/lib/omnizip/platform/ntfs_streams.rb +200 -0
- data/lib/omnizip/platform.rb +189 -0
- data/lib/omnizip/profile/archive_profile.rb +36 -0
- data/lib/omnizip/profile/balanced_profile.rb +31 -0
- data/lib/omnizip/profile/binary_profile.rb +33 -0
- data/lib/omnizip/profile/compression_profile.rb +157 -0
- data/lib/omnizip/profile/custom_profile.rb +155 -0
- data/lib/omnizip/profile/fast_profile.rb +31 -0
- data/lib/omnizip/profile/maximum_profile.rb +31 -0
- data/lib/omnizip/profile/profile_detector.rb +108 -0
- data/lib/omnizip/profile/profile_registry.rb +160 -0
- data/lib/omnizip/profile/text_profile.rb +33 -0
- data/lib/omnizip/profile.rb +261 -0
- data/lib/omnizip/profiler/memory_profiler.rb +66 -0
- data/lib/omnizip/profiler/method_profiler.rb +49 -0
- data/lib/omnizip/profiler/report_generator.rb +158 -0
- data/lib/omnizip/profiler.rb +192 -0
- data/lib/omnizip/progress/callback_reporter.rb +34 -0
- data/lib/omnizip/progress/console_reporter.rb +59 -0
- data/lib/omnizip/progress/log_reporter.rb +89 -0
- data/lib/omnizip/progress/operation_progress.rb +118 -0
- data/lib/omnizip/progress/progress_bar.rb +156 -0
- data/lib/omnizip/progress/progress_reporter.rb +40 -0
- data/lib/omnizip/progress/progress_tracker.rb +215 -0
- data/lib/omnizip/progress/silent_reporter.rb +22 -0
- data/lib/omnizip/progress.rb +131 -0
- data/lib/omnizip/registry.rb +111 -0
- data/lib/omnizip/rubyzip_compat.rb +61 -0
- data/lib/omnizip/temp/safe_extract.rb +124 -0
- data/lib/omnizip/temp/temp_file.rb +123 -0
- data/lib/omnizip/temp/temp_file_pool.rb +109 -0
- data/lib/omnizip/temp.rb +184 -0
- data/lib/omnizip/version.rb +5 -0
- data/lib/omnizip/zip/entry.rb +160 -0
- data/lib/omnizip/zip/file.rb +485 -0
- data/lib/omnizip/zip/input_stream.rb +270 -0
- data/lib/omnizip/zip/output_stream.rb +320 -0
- data/lib/omnizip/zip.rb +23 -0
- data/lib/omnizip.rb +157 -0
- data/lib/tasks/msi_test_files.rake +66 -0
- data/lib/tasks/platform_gems.rake +147 -0
- data/lib/tasks/rust_backend.rake +48 -0
- data/readme-docs/advanced-features.adoc +514 -0
- data/readme-docs/api-usage.adoc +445 -0
- data/readme-docs/architecture.adoc +450 -0
- data/readme-docs/archive-formats.adoc +479 -0
- data/readme-docs/cli-usage.adoc +222 -0
- data/readme-docs/compression-algorithms.adoc +446 -0
- data/readme-docs/compression-profiles.adoc +247 -0
- data/readme-docs/encryption-checksums.adoc +328 -0
- data/readme-docs/format-converter.adoc +316 -0
- data/readme-docs/installation.adoc +228 -0
- data/readme-docs/par2-archives.adoc +608 -0
- data/readme-docs/performance-profiler.adoc +389 -0
- data/readme-docs/preprocessing-filters.adoc +280 -0
- data/vendor/libomnizip_ffi.so +0 -0
- data/xz-file-format-1.2.1.txt +1174 -0
- metadata +768 -0
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "tempfile"
|
|
5
|
+
require "tmpdir"
|
|
6
|
+
|
|
7
|
+
module Omnizip
|
|
8
|
+
module Formats
|
|
9
|
+
module Msi
|
|
10
|
+
# MSI Package Reader
|
|
11
|
+
#
|
|
12
|
+
# Handles parsing and extraction of MSI packages.
|
|
13
|
+
# Uses OLE storage internally for reading embedded cabinets
|
|
14
|
+
# and resolving directory paths.
|
|
15
|
+
class Reader
|
|
16
|
+
include Omnizip::Formats::Msi::Constants
|
|
17
|
+
|
|
18
|
+
# @return [String] Path to MSI file
|
|
19
|
+
attr_reader :path
|
|
20
|
+
|
|
21
|
+
# @return [Ole::Storage] OLE storage object
|
|
22
|
+
attr_reader :ole
|
|
23
|
+
|
|
24
|
+
# @return [StringPool] String pool for interned strings
|
|
25
|
+
attr_reader :string_pool
|
|
26
|
+
|
|
27
|
+
# @return [TableParser] Table parser
|
|
28
|
+
attr_reader :table_parser
|
|
29
|
+
|
|
30
|
+
# @return [CabExtractor] Cab extractor
|
|
31
|
+
attr_reader :cab_extractor
|
|
32
|
+
|
|
33
|
+
# @return [DirectoryResolver] Directory resolver
|
|
34
|
+
attr_reader :directory_resolver
|
|
35
|
+
|
|
36
|
+
# @return [Hash<String, String>] Component to directory mapping
|
|
37
|
+
attr_reader :component_dirs
|
|
38
|
+
|
|
39
|
+
# @return [Array<Entry>] File entries (from File table)
|
|
40
|
+
attr_reader :entries
|
|
41
|
+
|
|
42
|
+
# Initialize MSI package reader
|
|
43
|
+
#
|
|
44
|
+
# @param path [String] Path to MSI file
|
|
45
|
+
def initialize(path)
|
|
46
|
+
@path = path
|
|
47
|
+
@entries = nil
|
|
48
|
+
@component_dirs = {}
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Open MSI file and parse tables
|
|
52
|
+
#
|
|
53
|
+
# @return [Reader] self
|
|
54
|
+
def open
|
|
55
|
+
@ole = Ole::Storage.open(@path)
|
|
56
|
+
build_stream_name_map
|
|
57
|
+
@string_pool = StringPool.new(@ole, method(:read_stream))
|
|
58
|
+
@table_parser = TableParser.new(@string_pool, method(:read_stream))
|
|
59
|
+
@directory_resolver = DirectoryResolver.new(@table_parser.table(DIRECTORY_TABLE))
|
|
60
|
+
build_component_dirs
|
|
61
|
+
@cab_extractor = CabExtractor.new(@ole,
|
|
62
|
+
@table_parser.table(MEDIA_TABLE), @path, method(:read_stream))
|
|
63
|
+
self
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Close MSI file
|
|
67
|
+
def close
|
|
68
|
+
@ole&.close
|
|
69
|
+
@ole = nil
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Get file entries from File table
|
|
73
|
+
#
|
|
74
|
+
# @return [Array<Entry>] File entries
|
|
75
|
+
def files
|
|
76
|
+
@files ||= build_entries
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Alias for files
|
|
80
|
+
#
|
|
81
|
+
# @return [Array<Entry>] File entries
|
|
82
|
+
alias entries files
|
|
83
|
+
|
|
84
|
+
# Extract all files to output directory
|
|
85
|
+
#
|
|
86
|
+
# @param output_dir [String] Output directory path
|
|
87
|
+
# @return [Array<String>] Extracted file paths
|
|
88
|
+
def extract(output_dir)
|
|
89
|
+
FileUtils.mkdir_p(output_dir)
|
|
90
|
+
|
|
91
|
+
# Extract files from cabinets
|
|
92
|
+
cabinets = @cab_extractor.extract_cabinets
|
|
93
|
+
extracted_files = extract_from_cabinets(cabinets, output_dir)
|
|
94
|
+
|
|
95
|
+
# Clean up temp cabinet files
|
|
96
|
+
cleanup_cabinets(cabinets)
|
|
97
|
+
|
|
98
|
+
extracted_files
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Get information about MSI package
|
|
102
|
+
#
|
|
103
|
+
# @return [Hash] Package information
|
|
104
|
+
def info
|
|
105
|
+
{
|
|
106
|
+
path: @path,
|
|
107
|
+
file_count: files.size,
|
|
108
|
+
tables: @table_parser.table_names,
|
|
109
|
+
}
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
private
|
|
113
|
+
|
|
114
|
+
# Build stream name map for encoded stream names
|
|
115
|
+
def build_stream_name_map
|
|
116
|
+
@stream_name_map = {}
|
|
117
|
+
|
|
118
|
+
return unless @ole&.root
|
|
119
|
+
|
|
120
|
+
@ole.root.children.each do |child|
|
|
121
|
+
# Decode the stream name
|
|
122
|
+
encoded_name = child.name
|
|
123
|
+
decoded_name = decode_stream_name(encoded_name)
|
|
124
|
+
@stream_name_map[decoded_name] = encoded_name
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Decode MSI stream name from OLE storage
|
|
129
|
+
#
|
|
130
|
+
# @param encoded_name [String] Encoded stream name
|
|
131
|
+
# @return [String] Decoded stream name
|
|
132
|
+
def decode_stream_name(encoded_name)
|
|
133
|
+
Constants.decode_stream_name(encoded_name)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Read stream from OLE storage
|
|
137
|
+
#
|
|
138
|
+
# @param base_name [String] Base stream name (e.g., "_StringPool")
|
|
139
|
+
# @return [String, nil] Stream content or nil
|
|
140
|
+
def read_stream(base_name)
|
|
141
|
+
# Try encoded name from the map first
|
|
142
|
+
if @stream_name_map&.key?(base_name)
|
|
143
|
+
encoded = @stream_name_map[base_name]
|
|
144
|
+
data = try_read_stream(encoded)
|
|
145
|
+
return data if data && !data.empty?
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Try various encodings of the stream name
|
|
149
|
+
candidates = build_stream_name_candidates(base_name)
|
|
150
|
+
|
|
151
|
+
candidates.each do |name|
|
|
152
|
+
data = try_read_stream(name)
|
|
153
|
+
return data if data && !data.empty?
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
nil
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Build possible stream name variations
|
|
160
|
+
#
|
|
161
|
+
# @param base_name [String] Base stream name
|
|
162
|
+
# @return [Array<String>] Possible stream names
|
|
163
|
+
def build_stream_name_candidates(base_name)
|
|
164
|
+
candidates = []
|
|
165
|
+
|
|
166
|
+
# Try with standard prefix bytes
|
|
167
|
+
# MSI uses \x01 or \x05 prefix followed by UTF-16LE encoded name
|
|
168
|
+
utf16le = base_name.encode("UTF-16LE")
|
|
169
|
+
[1, 5].each do |prefix|
|
|
170
|
+
candidates << prefix.chr.b.to_s.b << utf16le.b
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Try plain ASCII name
|
|
174
|
+
candidates << base_name
|
|
175
|
+
|
|
176
|
+
candidates.uniq
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# Attempt to read a stream
|
|
180
|
+
#
|
|
181
|
+
# @param name [String] Stream name
|
|
182
|
+
# @return [String, nil] Stream content or nil
|
|
183
|
+
def try_read_stream(name)
|
|
184
|
+
@ole.read(name)
|
|
185
|
+
rescue StandardError
|
|
186
|
+
nil
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# Build component to directory mapping from Component table
|
|
190
|
+
def build_component_dirs
|
|
191
|
+
component_table = @table_parser.table(COMPONENT_TABLE)
|
|
192
|
+
return unless component_table
|
|
193
|
+
|
|
194
|
+
component_table.each do |row|
|
|
195
|
+
component_key = row["Component"]
|
|
196
|
+
dir_key = row["Directory_"]
|
|
197
|
+
@component_dirs[component_key] = dir_key if component_key && dir_key
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# Build file entries from File table
|
|
202
|
+
#
|
|
203
|
+
# @return [Array<Entry>] File entries
|
|
204
|
+
def build_entries
|
|
205
|
+
entries = []
|
|
206
|
+
|
|
207
|
+
file_table = @table_parser.table(FILE_TABLE)
|
|
208
|
+
return entries if file_table.nil? || file_table.empty?
|
|
209
|
+
|
|
210
|
+
file_table.each do |row|
|
|
211
|
+
entry = Entry.new
|
|
212
|
+
entry.file_key = row["File"]
|
|
213
|
+
entry.component = row["Component_"]
|
|
214
|
+
entry.parse_filename(row["FileName"])
|
|
215
|
+
entry.size = row["FileSize"] || 0
|
|
216
|
+
entry.sequence = row["Sequence"] || 0
|
|
217
|
+
entry.version = row["Version"]
|
|
218
|
+
entry.language = row["Language"]
|
|
219
|
+
entry.attributes = row["Attributes"]
|
|
220
|
+
|
|
221
|
+
# Resolve directory path
|
|
222
|
+
dir_key = @component_dirs[entry.component]
|
|
223
|
+
dir_path = @directory_resolver&.resolve_path(dir_key) || ""
|
|
224
|
+
|
|
225
|
+
entry.path = File.join(dir_path, entry.display_name)
|
|
226
|
+
|
|
227
|
+
entries << entry
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
entries
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# Extract files from cabinets to output directory
|
|
234
|
+
# Maps cabinet file names to proper MSI file paths
|
|
235
|
+
#
|
|
236
|
+
# @param cabinets [Hash] Cabinet info from CabExtractor
|
|
237
|
+
# @param output_dir [String] Output directory
|
|
238
|
+
# @return [Array<String>] Extracted file paths
|
|
239
|
+
def extract_from_cabinets(cabinets, output_dir)
|
|
240
|
+
require "cabriolet"
|
|
241
|
+
|
|
242
|
+
extracted_files = []
|
|
243
|
+
decompressor = Cabriolet::CAB::Decompressor.new
|
|
244
|
+
|
|
245
|
+
# Build file key to entry mapping
|
|
246
|
+
file_key_map = {}
|
|
247
|
+
files.each do |entry|
|
|
248
|
+
file_key_map[entry.file_key] = entry
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# Process each cabinet
|
|
252
|
+
cabinets.each_value do |cab_info|
|
|
253
|
+
next unless cab_info[:path] && File.exist?(cab_info[:path])
|
|
254
|
+
|
|
255
|
+
# Extract to temp directory first
|
|
256
|
+
Dir.mktmpdir("msi_cab_extract") do |temp_dir|
|
|
257
|
+
cabinet = decompressor.open(cab_info[:path])
|
|
258
|
+
decompressor.extract_all(cabinet, temp_dir)
|
|
259
|
+
|
|
260
|
+
# Rename extracted files to proper paths
|
|
261
|
+
Dir.glob("#{temp_dir}/**/*").each do |temp_file|
|
|
262
|
+
next unless File.file?(temp_file)
|
|
263
|
+
|
|
264
|
+
# Get the base name (cabinet internal name)
|
|
265
|
+
cab_name = File.basename(temp_file)
|
|
266
|
+
|
|
267
|
+
# Look up the entry by file key
|
|
268
|
+
entry = file_key_map[cab_name]
|
|
269
|
+
target_path = if entry
|
|
270
|
+
# Use the proper path from the entry
|
|
271
|
+
File.join(output_dir, entry.path)
|
|
272
|
+
else
|
|
273
|
+
# Fallback: use cabinet name in output dir
|
|
274
|
+
File.join(output_dir, cab_name)
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
# Create target directory and move file
|
|
278
|
+
FileUtils.mkdir_p(File.dirname(target_path))
|
|
279
|
+
FileUtils.mv(temp_file, target_path)
|
|
280
|
+
extracted_files << target_path
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
extracted_files
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
# Clean up temporary cabinet files
|
|
289
|
+
#
|
|
290
|
+
# @param cabinets [Hash] Cabinet info from CabExtractor
|
|
291
|
+
def cleanup_cabinets(cabinets)
|
|
292
|
+
cabinets.each_value do |cab_info|
|
|
293
|
+
cab_info[:temp_file]&.close!
|
|
294
|
+
rescue StandardError
|
|
295
|
+
# Ignore errors during cleanup
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
end
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "set"
|
|
5
|
+
require "tempfile"
|
|
6
|
+
|
|
7
|
+
module Omnizip
|
|
8
|
+
module Formats
|
|
9
|
+
module Msi
|
|
10
|
+
# MSI String Pool
|
|
11
|
+
#
|
|
12
|
+
# Manages the interned string pool used by MSI files.
|
|
13
|
+
# Strings are stored in _StringPool (UTF-16LE data with length prefix)
|
|
14
|
+
# and _StringData (raw concatenated data).
|
|
15
|
+
#
|
|
16
|
+
# Based on Wine's msi_load_string_table implementation.
|
|
17
|
+
class StringPool
|
|
18
|
+
include Omnizip::Formats::Msi::Constants
|
|
19
|
+
|
|
20
|
+
# @return [Ole::Storage] OLE storage reference
|
|
21
|
+
attr_reader :ole
|
|
22
|
+
|
|
23
|
+
# @return [Array<String>] Decoded strings indexed by pool position (1-based)
|
|
24
|
+
attr_reader :strings
|
|
25
|
+
|
|
26
|
+
# @return [Integer] Codepage for string encoding
|
|
27
|
+
attr_reader :codepage
|
|
28
|
+
|
|
29
|
+
# @return [Hash] Stream name map (decoded name => encoded name)
|
|
30
|
+
attr_reader :stream_name_map
|
|
31
|
+
|
|
32
|
+
# Initialize string pool from OLE storage
|
|
33
|
+
#
|
|
34
|
+
# @param ole [Ole::Storage] OLE storage object
|
|
35
|
+
# @param stream_reader [Proc, Optional proc to read streams
|
|
36
|
+
def initialize(ole, stream_reader = nil)
|
|
37
|
+
@ole = ole
|
|
38
|
+
@strings = [nil] # Index 0 is unused (1-based indexing)
|
|
39
|
+
@codepage = 0
|
|
40
|
+
@pool_cache = {}
|
|
41
|
+
@stream_name_map = {}
|
|
42
|
+
@stream_reader = stream_reader
|
|
43
|
+
load
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Look up string by index
|
|
47
|
+
#
|
|
48
|
+
# @param index [Integer] String index (1-based)
|
|
49
|
+
# @return [String, nil] Decoded string or nil if not found
|
|
50
|
+
def [](index)
|
|
51
|
+
return nil if index.nil? || index <= 0
|
|
52
|
+
|
|
53
|
+
@strings[index]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Get string count
|
|
57
|
+
#
|
|
58
|
+
# @return [Integer]
|
|
59
|
+
def size
|
|
60
|
+
@strings.size - 1 # Subtract 1 for nil at index 0
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Read stream from OLE, handling MSI stream name encoding
|
|
64
|
+
#
|
|
65
|
+
# @param base_name [String] Base stream name (e.g., "_StringPool")
|
|
66
|
+
# @return [String, nil] Stream content or nil
|
|
67
|
+
def read_stream(base_name)
|
|
68
|
+
# Try various encodings of the stream name
|
|
69
|
+
candidates = build_stream_name_candidates(base_name)
|
|
70
|
+
|
|
71
|
+
candidates.each do |name|
|
|
72
|
+
data = try_read_stream(name)
|
|
73
|
+
return data if data && !data.empty?
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
nil
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
private
|
|
80
|
+
|
|
81
|
+
# Build possible stream name variations
|
|
82
|
+
#
|
|
83
|
+
# @param base_name [String] Base stream name
|
|
84
|
+
# @return [Array<String>] Possible stream names
|
|
85
|
+
def build_stream_name_candidates(base_name)
|
|
86
|
+
candidates = []
|
|
87
|
+
|
|
88
|
+
# Try encoded name from the map first (set by Reader)
|
|
89
|
+
if @stream_name_map&.key?(base_name)
|
|
90
|
+
candidates << @stream_name_map[base_name]
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Try with standard prefix bytes
|
|
94
|
+
# MSI uses \x01 prefix followed by UTF-16LE encoded name
|
|
95
|
+
utf16le = base_name.encode("UTF-16LE")
|
|
96
|
+
[1, 5].each do |prefix|
|
|
97
|
+
candidates << prefix.chr.b.to_s.b << utf16le.b
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Try plain ASCII name
|
|
101
|
+
candidates << base_name
|
|
102
|
+
|
|
103
|
+
candidates.uniq
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Load string pool and string data from OLE streams
|
|
107
|
+
def load
|
|
108
|
+
# Use the provided stream reader if available, otherwise use our own
|
|
109
|
+
reader = @stream_reader || method(:read_stream)
|
|
110
|
+
|
|
111
|
+
# Read string pool - contains metadata about strings
|
|
112
|
+
# Format: codepage (2 bytes) + reserved (2 bytes) + entries
|
|
113
|
+
pool_data = reader.call(STRING_POOL_STREAM)
|
|
114
|
+
return if pool_data.nil? || pool_data.empty?
|
|
115
|
+
|
|
116
|
+
# Read string data - contains raw concatenated string data
|
|
117
|
+
data = reader.call(STRING_DATA_STREAM)
|
|
118
|
+
return if data.nil? || data.empty?
|
|
119
|
+
|
|
120
|
+
# Parse pool header (first 2 bytes contain codepage info)
|
|
121
|
+
@codepage = pool_data[0, 2].unpack1("v") if pool_data.bytesize >= 2
|
|
122
|
+
|
|
123
|
+
# Parse string pool and data
|
|
124
|
+
parse_pool_and_data(pool_data[4..], data)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Attempt to read a stream
|
|
128
|
+
#
|
|
129
|
+
# @param name [String] Stream name
|
|
130
|
+
# @return [String, nil] Stream content or nil
|
|
131
|
+
def try_read_stream(name)
|
|
132
|
+
@ole.read(name)
|
|
133
|
+
rescue StandardError
|
|
134
|
+
nil
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Parse string pool and data streams
|
|
138
|
+
#
|
|
139
|
+
# _StringPool format:
|
|
140
|
+
# - Header: codepage (2 bytes) + reserved (2 bytes)
|
|
141
|
+
# - Entries: (2-byte length + 2-byte ref_count) for each string
|
|
142
|
+
#
|
|
143
|
+
# _StringData format:
|
|
144
|
+
# - Raw concatenated string data
|
|
145
|
+
#
|
|
146
|
+
# @param pool [String] Pool data (after header)
|
|
147
|
+
# @param data [String] String data stream
|
|
148
|
+
def parse_pool_and_data(pool, data)
|
|
149
|
+
return if pool.nil? || pool.empty? || data.nil? || data.empty?
|
|
150
|
+
|
|
151
|
+
# Calculate number of entries (each entry is 4 bytes: 2 for length + 2 for refs)
|
|
152
|
+
num_entries = pool.bytesize / 4
|
|
153
|
+
|
|
154
|
+
# Read entry metadata from pool
|
|
155
|
+
entries = []
|
|
156
|
+
num_entries.times do |i|
|
|
157
|
+
offset = i * 4
|
|
158
|
+
length = pool[offset, 2].unpack1("v")
|
|
159
|
+
ref_count = pool[offset + 2, 2].unpack1("v")
|
|
160
|
+
entries << { length: length, ref_count: ref_count }
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Read strings from data stream
|
|
164
|
+
data_offset = 0
|
|
165
|
+
entries.each do |entry|
|
|
166
|
+
length = entry[:length]
|
|
167
|
+
if length.positive? && data_offset + length <= data.bytesize
|
|
168
|
+
str_data = data[data_offset, length]
|
|
169
|
+
@strings << decode_string(str_data)
|
|
170
|
+
data_offset += length
|
|
171
|
+
else
|
|
172
|
+
@strings << ""
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Decode string from string data stream
|
|
178
|
+
#
|
|
179
|
+
# Strings are stored in the MSI's codepage (typically Windows-1252).
|
|
180
|
+
#
|
|
181
|
+
# @param data [String] Raw string bytes
|
|
182
|
+
# @return [String] Decoded UTF-8 string
|
|
183
|
+
def decode_string(data)
|
|
184
|
+
return "" if data.nil? || data.empty?
|
|
185
|
+
|
|
186
|
+
# Try codepage encoding if set
|
|
187
|
+
if @codepage.positive? && @codepage != 65001 # 65001 is UTF-8
|
|
188
|
+
begin
|
|
189
|
+
# Map common MSI codepages to Ruby encodings
|
|
190
|
+
encoding = codepage_to_encoding(@codepage)
|
|
191
|
+
return data.force_encoding(encoding).encode("UTF-8",
|
|
192
|
+
invalid: :replace, undef: :replace)
|
|
193
|
+
rescue StandardError
|
|
194
|
+
# Fall through
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# Try UTF-8 first (common for newer MSIs)
|
|
199
|
+
begin
|
|
200
|
+
if data.valid_encoding?
|
|
201
|
+
return data.encode("UTF-8", invalid: :replace,
|
|
202
|
+
undef: :replace)
|
|
203
|
+
end
|
|
204
|
+
rescue StandardError
|
|
205
|
+
# Fall through
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Try Windows-1252 (most common MSI codepage)
|
|
209
|
+
begin
|
|
210
|
+
return data.force_encoding("Windows-1252").encode("UTF-8",
|
|
211
|
+
invalid: :replace, undef: :replace)
|
|
212
|
+
rescue StandardError
|
|
213
|
+
# Fall through
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# Fallback to binary
|
|
217
|
+
data.force_encoding("BINARY")
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# Map Windows codepage to Ruby encoding name
|
|
221
|
+
#
|
|
222
|
+
# @param codepage [Integer] Windows codepage number
|
|
223
|
+
# @return [String, nil] Ruby encoding name
|
|
224
|
+
def codepage_to_encoding(codepage)
|
|
225
|
+
case codepage
|
|
226
|
+
when 1252, 0 then "Windows-1252"
|
|
227
|
+
when 1250 then "Windows-1250"
|
|
228
|
+
when 1251 then "Windows-1251"
|
|
229
|
+
when 1253 then "Windows-1253"
|
|
230
|
+
when 1254 then "Windows-1254"
|
|
231
|
+
when 1255 then "Windows-1255"
|
|
232
|
+
when 1256 then "Windows-1256"
|
|
233
|
+
when 1257 then "Windows-1257"
|
|
234
|
+
when 1258 then "Windows-1258"
|
|
235
|
+
when 932 then "Windows-31J"
|
|
236
|
+
when 936 then "GB2312"
|
|
237
|
+
when 949 then "EUC-KR"
|
|
238
|
+
when 950 then "Big5"
|
|
239
|
+
when 65001 then "UTF-8"
|
|
240
|
+
else "Windows-1252"
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
end
|