omnizip 0.4.7-arm-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,133 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Formats
|
|
5
|
+
# ISO 9660 CD-ROM filesystem format support
|
|
6
|
+
#
|
|
7
|
+
# Reads and writes ISO 9660 images: Primary Volume Descriptor
|
|
8
|
+
# parsing, directory traversal, file extraction, and image
|
|
9
|
+
# creation whose directory records point at allocated extents
|
|
10
|
+
# (verified against 7-Zip). Rock Ridge and Joliet are NOT
|
|
11
|
+
# implemented — the writer's options stay false rather than
|
|
12
|
+
# advertising extensions readers would misparse.
|
|
13
|
+
module Iso
|
|
14
|
+
# Nested classes - autoloaded
|
|
15
|
+
autoload :Reader, "omnizip/formats/iso/reader"
|
|
16
|
+
autoload :Writer, "omnizip/formats/iso/writer"
|
|
17
|
+
autoload :VolumeDescriptor, "omnizip/formats/iso/volume_descriptor"
|
|
18
|
+
autoload :VolumeBuilder, "omnizip/formats/iso/volume_builder"
|
|
19
|
+
autoload :DirectoryRecord, "omnizip/formats/iso/directory_record"
|
|
20
|
+
autoload :DirectoryBuilder, "omnizip/formats/iso/directory_builder"
|
|
21
|
+
autoload :PathTable, "omnizip/formats/iso/path_table"
|
|
22
|
+
autoload :RockRidge, "omnizip/formats/iso/rock_ridge"
|
|
23
|
+
autoload :Joliet, "omnizip/formats/iso/joliet"
|
|
24
|
+
|
|
25
|
+
# ISO 9660 constants
|
|
26
|
+
SECTOR_SIZE = 2048
|
|
27
|
+
SYSTEM_AREA_SECTORS = 16
|
|
28
|
+
VOLUME_DESCRIPTOR_START = SYSTEM_AREA_SECTORS
|
|
29
|
+
|
|
30
|
+
# Volume descriptor types
|
|
31
|
+
VD_BOOT_RECORD = 0
|
|
32
|
+
VD_PRIMARY = 1
|
|
33
|
+
VD_SUPPLEMENTARY = 2
|
|
34
|
+
VD_PARTITION = 3
|
|
35
|
+
VD_TERMINATOR = 255
|
|
36
|
+
|
|
37
|
+
# File flags
|
|
38
|
+
FLAG_HIDDEN = 0x01
|
|
39
|
+
FLAG_DIRECTORY = 0x02
|
|
40
|
+
FLAG_ASSOCIATED = 0x04
|
|
41
|
+
FLAG_EXTENDED = 0x08
|
|
42
|
+
FLAG_PERMISSIONS = 0x10
|
|
43
|
+
FLAG_NOT_FINAL = 0x80
|
|
44
|
+
|
|
45
|
+
# Open existing ISO image
|
|
46
|
+
#
|
|
47
|
+
# @param path [String] Path to ISO file
|
|
48
|
+
# @yield [reader] Block for reading archive
|
|
49
|
+
# @yieldparam reader [Reader] ISO reader
|
|
50
|
+
# @return [Reader] ISO reader
|
|
51
|
+
def self.open(path)
|
|
52
|
+
reader = Reader.new(path)
|
|
53
|
+
reader.open
|
|
54
|
+
|
|
55
|
+
if block_given?
|
|
56
|
+
begin
|
|
57
|
+
yield reader
|
|
58
|
+
ensure
|
|
59
|
+
reader.close
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
reader
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# List contents of ISO image
|
|
67
|
+
#
|
|
68
|
+
# @param path [String] Path to ISO file
|
|
69
|
+
# @return [Array<DirectoryRecord>] Directory entries
|
|
70
|
+
def self.list(path)
|
|
71
|
+
entries = nil
|
|
72
|
+
open(path) { |iso| entries = iso.entries }
|
|
73
|
+
entries
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Extract ISO contents
|
|
77
|
+
#
|
|
78
|
+
# @param iso_path [String] Path to ISO file
|
|
79
|
+
# @param output_dir [String] Output directory
|
|
80
|
+
def self.extract(iso_path, output_dir)
|
|
81
|
+
open(iso_path) do |iso|
|
|
82
|
+
iso.extract_all(output_dir)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Get ISO volume information
|
|
87
|
+
#
|
|
88
|
+
# @param path [String] Path to ISO file
|
|
89
|
+
# @return [Hash] Volume information
|
|
90
|
+
def self.info(path)
|
|
91
|
+
open(path) do |iso|
|
|
92
|
+
{
|
|
93
|
+
format: "ISO 9660",
|
|
94
|
+
volume_id: iso.volume_identifier,
|
|
95
|
+
system_id: iso.system_identifier,
|
|
96
|
+
size: iso.volume_size,
|
|
97
|
+
files: iso.entries.count { |e| !e.directory? },
|
|
98
|
+
directories: iso.entries.count(&:directory?),
|
|
99
|
+
}
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Create ISO 9660 image
|
|
104
|
+
#
|
|
105
|
+
# @param path [String] Output ISO file path
|
|
106
|
+
# @param options [Hash] Creation options
|
|
107
|
+
# @yield [writer] Block for adding files/directories
|
|
108
|
+
# @yieldparam writer [Writer] ISO writer
|
|
109
|
+
# @return [String] Path to created ISO
|
|
110
|
+
#
|
|
111
|
+
# @example Create ISO image
|
|
112
|
+
# Omnizip::Formats::Iso.create('backup.iso') do |iso|
|
|
113
|
+
# iso.volume_id = 'BACKUP_2024'
|
|
114
|
+
# iso.add_directory('documents/')
|
|
115
|
+
# end
|
|
116
|
+
#
|
|
117
|
+
# @example With Rock Ridge and Joliet
|
|
118
|
+
# Omnizip::Formats::Iso.create('cdrom.iso',
|
|
119
|
+
# rock_ridge: true,
|
|
120
|
+
# joliet: true
|
|
121
|
+
# ) do |iso|
|
|
122
|
+
# iso.add_directory('files/')
|
|
123
|
+
# end
|
|
124
|
+
def self.create(path, options = {})
|
|
125
|
+
writer = Writer.new(path, options)
|
|
126
|
+
|
|
127
|
+
yield writer if block_given?
|
|
128
|
+
|
|
129
|
+
writer.write
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "stringio"
|
|
4
|
+
|
|
5
|
+
module Omnizip
|
|
6
|
+
module Formats
|
|
7
|
+
#
|
|
8
|
+
# LZIP (.lz) compression format
|
|
9
|
+
#
|
|
10
|
+
# Lzip is a file compression format that uses LZMA compression with a
|
|
11
|
+
# simple container format. It was created as an alternative to the
|
|
12
|
+
# legacy .lzma format with better integrity checking.
|
|
13
|
+
#
|
|
14
|
+
# This is DIFFERENT from both XZ and .lzma (LZMA_Alone) formats:
|
|
15
|
+
# - XZ (.xz): Container format with stream header/footer/index, LZMA2 compression
|
|
16
|
+
# - LZIP (.lz): Standalone format with "LZIP" magic and CRC32 footer, LZMA1 compression
|
|
17
|
+
# - LZMA_Alone (.lzma): Legacy standalone format with properties byte, LZMA1 compression
|
|
18
|
+
#
|
|
19
|
+
# Format structure:
|
|
20
|
+
# - Header (6 bytes):
|
|
21
|
+
# - Magic bytes: "LZIP" (0x4C 0x5A 0x49 0x50)
|
|
22
|
+
# - Version (1 byte): 0 or 1
|
|
23
|
+
# - Dictionary size (1 byte): encoded format
|
|
24
|
+
# - LZMA1 compressed stream (with fixed LC=3, LP=0, PB=2)
|
|
25
|
+
# - Footer:
|
|
26
|
+
# - Version 0 (12 bytes): CRC32 (4) + Uncompressed size (8)
|
|
27
|
+
# - Version 1 (20 bytes): CRC32 (4) + Uncompressed size (8) + Member size (8)
|
|
28
|
+
#
|
|
29
|
+
# Reference: /Users/mulgogi/src/external/xz/src/liblzma/common/lzip_decoder.c
|
|
30
|
+
#
|
|
31
|
+
module Lzip
|
|
32
|
+
# Lzip magic bytes: "LZIP" in ASCII
|
|
33
|
+
# Reference: lzip_decoder.c:106
|
|
34
|
+
MAGIC = [0x4C, 0x5A, 0x49, 0x50].pack("C*")
|
|
35
|
+
|
|
36
|
+
# Fixed LC/LP/PB values for lzip format
|
|
37
|
+
# Reference: lzip_decoder.c:23-26
|
|
38
|
+
LZIP_LC = 3
|
|
39
|
+
LZIP_LP = 0
|
|
40
|
+
LZIP_PB = 2
|
|
41
|
+
|
|
42
|
+
# Minimum and maximum dictionary sizes (in bytes)
|
|
43
|
+
# Reference: lzip_decoder.c:197-198
|
|
44
|
+
MIN_DICT_SIZE = 4096 # 4 KiB
|
|
45
|
+
MAX_DICT_SIZE = (512 << 20) # 512 MiB
|
|
46
|
+
|
|
47
|
+
class << self
|
|
48
|
+
# Compress a file with LZIP
|
|
49
|
+
#
|
|
50
|
+
# @param input_path [String] Input file path
|
|
51
|
+
# @param output_path [String] Output LZIP file path
|
|
52
|
+
# @param options [Hash] Compression options
|
|
53
|
+
# @option options [Integer] :level Compression level (0-9, default: 6)
|
|
54
|
+
# @option options [Integer] :dict_size Dictionary size (default: auto from level)
|
|
55
|
+
# @option options [Integer] :version LZIP version (0 or 1, default: 1)
|
|
56
|
+
def compress(input_path, output_path, options = {})
|
|
57
|
+
input_data = File.binread(input_path)
|
|
58
|
+
|
|
59
|
+
File.open(output_path, "wb") do |output|
|
|
60
|
+
compress_stream(
|
|
61
|
+
StringIO.new(input_data),
|
|
62
|
+
output,
|
|
63
|
+
options,
|
|
64
|
+
)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Decompress LZIP data
|
|
69
|
+
#
|
|
70
|
+
# @param input [String, IO] Input data, file path, or IO object
|
|
71
|
+
# @param output [String, IO, nil] Output file path or IO object
|
|
72
|
+
# @param options [Hash] Options
|
|
73
|
+
# @option options [Boolean] :ignore_check If true, skip CRC32 verification (default: false)
|
|
74
|
+
# @option options [Boolean] :concatenated If true, decode concatenated .lz members (default: false)
|
|
75
|
+
# @return [String, nil] Decompressed data (if output is nil)
|
|
76
|
+
def decompress(input, output = nil, options = {})
|
|
77
|
+
data = Omnizip::IO::Source.for(input).read
|
|
78
|
+
|
|
79
|
+
# Decode using LzipDecoder
|
|
80
|
+
decoder = Omnizip::Algorithms::LZMA::LzipDecoder.new(
|
|
81
|
+
StringIO.new(data),
|
|
82
|
+
options,
|
|
83
|
+
)
|
|
84
|
+
result = decoder.decode_stream
|
|
85
|
+
|
|
86
|
+
if output
|
|
87
|
+
Omnizip::IO::Sink.for(output).write(result)
|
|
88
|
+
else
|
|
89
|
+
result
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Decode LZIP data (alias for decompress with no output)
|
|
94
|
+
#
|
|
95
|
+
# @param input [String, IO] Input LZIP data or file path
|
|
96
|
+
# @return [String] Decompressed data
|
|
97
|
+
def decode(input)
|
|
98
|
+
decompress(input)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Compress data stream with LZIP
|
|
102
|
+
#
|
|
103
|
+
# @param input_io [IO] Input stream
|
|
104
|
+
# @param output_io [IO] Output stream
|
|
105
|
+
# @param options [Hash] Compression options
|
|
106
|
+
def compress_stream(input_io, output_io, options = {})
|
|
107
|
+
input = input_io.read
|
|
108
|
+
|
|
109
|
+
# Version-1 member: magic + version + dict-size byte, LZMA1
|
|
110
|
+
# body (EOPM-terminated), 20-byte trailer (CRC32 + data
|
|
111
|
+
# size + member size). The dictionary byte uses lzip's
|
|
112
|
+
# 5-bit exponent / 3-bit fraction encoding; 4 MiB is the
|
|
113
|
+
# typical default.
|
|
114
|
+
output_io.write(MAGIC)
|
|
115
|
+
output_io.write([1].pack("C"))
|
|
116
|
+
output_io.write([22].pack("C")) # 2^22 = 4 MiB, no fraction
|
|
117
|
+
|
|
118
|
+
dict_size = options.fetch(:dict_size, 8 * 1024 * 1024)
|
|
119
|
+
body = Algorithms::LZMA::Lzma1Encoder
|
|
120
|
+
.new(dict_size: dict_size).encode(input)
|
|
121
|
+
|
|
122
|
+
member_size = 6 + body.bytesize + 20
|
|
123
|
+
output_io.write(body)
|
|
124
|
+
output_io.write([Checksums::Crc32.calculate(input)].pack("V"))
|
|
125
|
+
output_io.write([input.bytesize].pack("Q<"))
|
|
126
|
+
output_io.write([member_size].pack("Q<"))
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Decompress LZIP stream
|
|
130
|
+
#
|
|
131
|
+
# @param input_io [IO] Input stream
|
|
132
|
+
# @param output_io [IO] Output stream
|
|
133
|
+
# @param options [Hash] Options
|
|
134
|
+
# @return [Hash] Metadata (version, dict_size, member_size)
|
|
135
|
+
def decompress_stream(input_io, output_io, options = {})
|
|
136
|
+
output_io.set_encoding(Encoding::BINARY)
|
|
137
|
+
decoder = Omnizip::Algorithms::LZMA::LzipDecoder.new(input_io,
|
|
138
|
+
options)
|
|
139
|
+
result = decoder.decode_stream
|
|
140
|
+
|
|
141
|
+
output_io.write(result)
|
|
142
|
+
|
|
143
|
+
# Return metadata
|
|
144
|
+
{
|
|
145
|
+
version: decoder.version,
|
|
146
|
+
dict_size: decoder.dict_size,
|
|
147
|
+
member_size: decoder.member_size,
|
|
148
|
+
}
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Detect if data is LZIP format
|
|
152
|
+
#
|
|
153
|
+
# @param data [String] Data to check
|
|
154
|
+
# @return [Boolean] true if data has LZIP magic bytes
|
|
155
|
+
def lzip_file?(data)
|
|
156
|
+
data.start_with?(MAGIC)
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "stringio"
|
|
4
|
+
|
|
5
|
+
module Omnizip
|
|
6
|
+
module Formats
|
|
7
|
+
#
|
|
8
|
+
# LZMA_Alone (.lzma) compression format
|
|
9
|
+
#
|
|
10
|
+
# This is the legacy LZMA_Alone format used by LZMA Utils 4.32.x.
|
|
11
|
+
# It is DIFFERENT from both XZ and LZIP formats:
|
|
12
|
+
# - XZ (.xz): Container format with stream header/footer/index, LZMA2 compression
|
|
13
|
+
# - LZIP (.lz): Standalone format with "LZIP" magic and CRC32 footer, LZMA1 compression
|
|
14
|
+
# - LZMA_Alone (.lzma): Legacy standalone format with properties byte, LZMA1 compression
|
|
15
|
+
#
|
|
16
|
+
# Format structure:
|
|
17
|
+
# - Properties (1 byte): encodes lc, lp, pb values
|
|
18
|
+
# - Dictionary size (4 bytes, little-endian)
|
|
19
|
+
# - Uncompressed size (8 bytes, little-endian, UINT64_MAX = unknown)
|
|
20
|
+
# - LZMA1 compressed stream (no footer, no CRC32)
|
|
21
|
+
#
|
|
22
|
+
# Reference: /Users/mulgogi/src/external/xz/src/liblzma/common/alone_decoder.c
|
|
23
|
+
#
|
|
24
|
+
module LzmaAlone
|
|
25
|
+
# Maximum valid uncompressed size (256 GiB)
|
|
26
|
+
# From alone_decoder.c:118
|
|
27
|
+
MAX_UNCOMPRESSED_SIZE = (1 << 38)
|
|
28
|
+
|
|
29
|
+
# Property byte validation limits
|
|
30
|
+
# From lzma_decoder.c:1218
|
|
31
|
+
MAX_PROPERTY_BYTE = (((4 * 5) + 4) * 9) + 8 # = 233
|
|
32
|
+
|
|
33
|
+
# Value indicating unknown uncompressed size
|
|
34
|
+
UINT64_MAX = (1 << 64) - 1
|
|
35
|
+
|
|
36
|
+
class << self
|
|
37
|
+
# Compress a file with LZMA_Alone format
|
|
38
|
+
#
|
|
39
|
+
# @param input_path [String] Input file path
|
|
40
|
+
# @param output_path [String] Output LZMA_Alone file path
|
|
41
|
+
# @param options [Hash] Compression options
|
|
42
|
+
# @option options [Integer] :lc Literal context bits (0-8, default: 3)
|
|
43
|
+
# @option options [Integer] :lp Literal position bits (0-4, default: 0)
|
|
44
|
+
# @option options [Integer] :pb Position bits (0-4, default: 2)
|
|
45
|
+
# @option options [Integer] :dict_size Dictionary size (default: 8MB)
|
|
46
|
+
# @option options [Integer] :uncompressed_size Explicit uncompressed size (default: unknown)
|
|
47
|
+
def compress(input_path, output_path, options = {})
|
|
48
|
+
input_data = File.binread(input_path)
|
|
49
|
+
|
|
50
|
+
File.open(output_path, "wb") do |output|
|
|
51
|
+
compress_stream(
|
|
52
|
+
StringIO.new(input_data),
|
|
53
|
+
output,
|
|
54
|
+
options,
|
|
55
|
+
)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Decompress LZMA_Alone data
|
|
60
|
+
#
|
|
61
|
+
# @param input [String, IO] Input data, file path, or IO object
|
|
62
|
+
# @param output [String, IO, nil] Output file path or IO object
|
|
63
|
+
# @param options [Hash] Options
|
|
64
|
+
# @option options [Boolean] :picky If true, reject files unlikely to be .lzma (default: false)
|
|
65
|
+
# @return [String, nil] Decompressed data (if output is nil)
|
|
66
|
+
def decompress(input, output = nil, options = {})
|
|
67
|
+
data = Omnizip::IO::Source.for(input).read
|
|
68
|
+
|
|
69
|
+
# Decode using LzmaAloneDecoder
|
|
70
|
+
decoder = Omnizip::Algorithms::LZMA::LzmaAloneDecoder.new(
|
|
71
|
+
StringIO.new(data),
|
|
72
|
+
options,
|
|
73
|
+
)
|
|
74
|
+
result = decoder.decode_stream
|
|
75
|
+
|
|
76
|
+
if output
|
|
77
|
+
Omnizip::IO::Sink.for(output).write(result)
|
|
78
|
+
else
|
|
79
|
+
result
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Decode LZMA_Alone data (alias for decompress with no output)
|
|
84
|
+
#
|
|
85
|
+
# @param input [String, IO] Input LZMA_Alone data or file path
|
|
86
|
+
# @return [String] Decompressed data
|
|
87
|
+
def decode(input)
|
|
88
|
+
decompress(input)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Compress data stream with LZMA_Alone format
|
|
92
|
+
#
|
|
93
|
+
# @param input_io [IO] Input stream
|
|
94
|
+
# @param output_io [IO] Output stream
|
|
95
|
+
# @param options [Hash] Compression options
|
|
96
|
+
def compress_stream(input_io, output_io, options = {})
|
|
97
|
+
input_data = input_io.read
|
|
98
|
+
|
|
99
|
+
# Get encoding parameters
|
|
100
|
+
lc = options[:lc] || 3
|
|
101
|
+
lp = options[:lp] || 0
|
|
102
|
+
pb = options[:pb] || 2
|
|
103
|
+
dict_size = options[:dict_size] || (8 * 1024 * 1024)
|
|
104
|
+
uncompressed_size = options[:uncompressed_size] || input_data.bytesize
|
|
105
|
+
|
|
106
|
+
# Encode properties byte
|
|
107
|
+
prop_byte = (((pb * 5) + lp) * 9) + lc
|
|
108
|
+
|
|
109
|
+
# Write header
|
|
110
|
+
output_io.write([prop_byte].pack("C"))
|
|
111
|
+
output_io.write([dict_size].pack("V"))
|
|
112
|
+
output_io.write([uncompressed_size].pack("Q<"))
|
|
113
|
+
|
|
114
|
+
# Raw LZMA1 body. The header carries the uncompressed size,
|
|
115
|
+
# but the EOPM is still emitted: the format permits it with
|
|
116
|
+
# a known size and it lets size-agnostic decoders stop too.
|
|
117
|
+
body = Algorithms::LZMA::Lzma1Encoder
|
|
118
|
+
.new(dict_size: dict_size, lc: lc, lp: lp, pb: pb)
|
|
119
|
+
.encode(input_data)
|
|
120
|
+
output_io.write(body)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Decompress LZMA_Alone stream
|
|
124
|
+
#
|
|
125
|
+
# @param input_io [IO] Input stream
|
|
126
|
+
# @param output_io [IO] Output stream
|
|
127
|
+
# @param options [Hash] Options
|
|
128
|
+
# @return [Hash] Metadata (lc, lp, pb, dict_size, uncompressed_size)
|
|
129
|
+
def decompress_stream(input_io, output_io, options = {})
|
|
130
|
+
output_io.set_encoding(Encoding::BINARY)
|
|
131
|
+
decoder = Omnizip::Algorithms::LZMA::LzmaAloneDecoder.new(input_io,
|
|
132
|
+
options)
|
|
133
|
+
result = decoder.decode_stream
|
|
134
|
+
|
|
135
|
+
output_io.write(result)
|
|
136
|
+
|
|
137
|
+
# Return metadata
|
|
138
|
+
{
|
|
139
|
+
lc: decoder.lc,
|
|
140
|
+
lp: decoder.lp,
|
|
141
|
+
pb: decoder.pb,
|
|
142
|
+
dict_size: decoder.dict_size,
|
|
143
|
+
uncompressed_size: decoder.uncompressed_size,
|
|
144
|
+
}
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "tempfile"
|
|
4
|
+
require "fileutils"
|
|
5
|
+
|
|
6
|
+
module Omnizip
|
|
7
|
+
module Formats
|
|
8
|
+
module Msi
|
|
9
|
+
# MSI CAB Extractor
|
|
10
|
+
#
|
|
11
|
+
# Handles extraction of files from embedded or external cabinet files.
|
|
12
|
+
# MSI packages can have cabinets embedded in the _Streams table or
|
|
13
|
+
# as separate .cab files alongside the MSI.
|
|
14
|
+
class CabExtractor
|
|
15
|
+
include Omnizip::Formats::Msi::Constants
|
|
16
|
+
|
|
17
|
+
# @return [Ole::Storage] OLE storage
|
|
18
|
+
attr_reader :ole
|
|
19
|
+
|
|
20
|
+
# @return [Array<Hash>] Media table data
|
|
21
|
+
attr_reader :media_table
|
|
22
|
+
|
|
23
|
+
# @return [String] Path to MSI file (for external CAB resolution)
|
|
24
|
+
attr_reader :msi_path
|
|
25
|
+
|
|
26
|
+
# @return [Proc] Stream reader method
|
|
27
|
+
attr_reader :read_stream
|
|
28
|
+
|
|
29
|
+
# Initialize CAB extractor
|
|
30
|
+
#
|
|
31
|
+
# @param ole [Ole::Storage] OLE storage object
|
|
32
|
+
# @param media_table [Array<Hash>] Parsed Media table rows
|
|
33
|
+
# @param msi_path [String] Path to MSI file
|
|
34
|
+
# @param stream_reader [Proc] Method to read streams
|
|
35
|
+
def initialize(ole, media_table, msi_path, stream_reader)
|
|
36
|
+
@ole = ole
|
|
37
|
+
@media_table = media_table || []
|
|
38
|
+
@msi_path = msi_path
|
|
39
|
+
@read_stream = stream_reader
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Extract all cabinets to temporary files
|
|
43
|
+
#
|
|
44
|
+
# @return [Hash] Map of cabinet name => temp file path
|
|
45
|
+
def extract_cabinets
|
|
46
|
+
cabinets = {}
|
|
47
|
+
|
|
48
|
+
@media_table.each do |media|
|
|
49
|
+
cab_name = media["Cabinet"]
|
|
50
|
+
next if cab_name.nil? || cab_name.empty?
|
|
51
|
+
|
|
52
|
+
cab_data = get_cabinet_data(cab_name)
|
|
53
|
+
next if cab_data.nil? || cab_data.empty?
|
|
54
|
+
|
|
55
|
+
# Write to temp file
|
|
56
|
+
temp_file = Tempfile.create(["msi_cab_", ".cab"])
|
|
57
|
+
temp_file.binmode
|
|
58
|
+
temp_file.write(cab_data)
|
|
59
|
+
temp_file.flush
|
|
60
|
+
temp_file.close
|
|
61
|
+
|
|
62
|
+
cabinets[media["DiskId"]] = {
|
|
63
|
+
path: temp_file.path,
|
|
64
|
+
name: cab_name,
|
|
65
|
+
last_sequence: media["LastSequence"],
|
|
66
|
+
temp_file: temp_file,
|
|
67
|
+
}
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
cabinets
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Get cabinet data for a media entry
|
|
74
|
+
#
|
|
75
|
+
# @param cabinet_name [String] Cabinet name from Media table
|
|
76
|
+
# @return [String, nil] Cabinet binary data or nil
|
|
77
|
+
def get_cabinet_data(cabinet_name)
|
|
78
|
+
return nil if cabinet_name.nil? || cabinet_name.empty?
|
|
79
|
+
|
|
80
|
+
if cabinet_name.start_with?(EMBEDDED_CAB_PREFIX)
|
|
81
|
+
# Embedded cabinet
|
|
82
|
+
extract_embedded_cabinet(cabinet_name[1..])
|
|
83
|
+
else
|
|
84
|
+
# External cabinet file
|
|
85
|
+
read_external_cabinet(cabinet_name)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Find the cabinet containing a file by sequence number
|
|
90
|
+
#
|
|
91
|
+
# @param sequence [Integer] File sequence number
|
|
92
|
+
# @param cabinets [Hash] Cabinet info from extract_cabinets
|
|
93
|
+
# @return [Hash, nil] Cabinet info or nil
|
|
94
|
+
def find_cabinet_for_sequence(sequence, cabinets)
|
|
95
|
+
# Sort by LastSequence and find the cabinet where sequence <= LastSequence
|
|
96
|
+
sorted = cabinets.values.sort_by { |c| c[:last_sequence] }
|
|
97
|
+
sorted.find { |c| sequence <= c[:last_sequence] }
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
private
|
|
101
|
+
|
|
102
|
+
# Extract embedded cabinet data
|
|
103
|
+
#
|
|
104
|
+
# Embedded cabinets can be in:
|
|
105
|
+
# 1. _Streams table (most common)
|
|
106
|
+
# 2. Direct OLE stream (rare)
|
|
107
|
+
#
|
|
108
|
+
# @param stream_name [String] Stream name (without # prefix)
|
|
109
|
+
# @return [String, nil] Cabinet data or nil
|
|
110
|
+
def extract_embedded_cabinet(stream_name)
|
|
111
|
+
return nil if stream_name.nil? || stream_name.empty?
|
|
112
|
+
|
|
113
|
+
# Try to read from OLE directly using various name encodings
|
|
114
|
+
candidates = build_stream_name_candidates(stream_name)
|
|
115
|
+
|
|
116
|
+
candidates.each do |name|
|
|
117
|
+
data = @read_stream.call(name)
|
|
118
|
+
return data if data && !data.empty? && valid_cab?(data)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Also try without # prefix but with standard prefixes
|
|
122
|
+
data = @read_stream.call(stream_name)
|
|
123
|
+
return data if data && !data.empty? && valid_cab?(data)
|
|
124
|
+
|
|
125
|
+
nil
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Build possible encoded stream name candidates
|
|
129
|
+
#
|
|
130
|
+
# @param name [String] Base stream name
|
|
131
|
+
# @return [Array<String>] Possible stream names
|
|
132
|
+
def build_stream_name_candidates(name)
|
|
133
|
+
candidates = []
|
|
134
|
+
|
|
135
|
+
# Try direct name
|
|
136
|
+
candidates << name
|
|
137
|
+
|
|
138
|
+
# Try with MSI stream name encoding prefix
|
|
139
|
+
# Use binary encoding for the prefix byte
|
|
140
|
+
utf16le = name.encode("UTF-16LE")
|
|
141
|
+
candidates << ("\x01".b << utf16le.dup.force_encoding("BINARY"))
|
|
142
|
+
candidates << ("\x05".b << utf16le.dup.force_encoding("BINARY"))
|
|
143
|
+
|
|
144
|
+
# Try without any prefix (plain ASCII)
|
|
145
|
+
candidates << name
|
|
146
|
+
|
|
147
|
+
candidates.uniq
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Check if data is a valid cabinet file
|
|
151
|
+
#
|
|
152
|
+
# @param data [String] Binary data
|
|
153
|
+
# @return [Boolean] true if valid CAB signature
|
|
154
|
+
def valid_cab?(data)
|
|
155
|
+
return false if data.nil? || data.bytesize < 4
|
|
156
|
+
|
|
157
|
+
# Check for MSCF signature
|
|
158
|
+
data[0, 4] == "MSCF"
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Read external cabinet file
|
|
162
|
+
#
|
|
163
|
+
# External cabinets are located in the same directory as the MSI.
|
|
164
|
+
#
|
|
165
|
+
# @param cabinet_name [String] Cabinet filename
|
|
166
|
+
# @return [String, nil] Cabinet data or nil
|
|
167
|
+
def read_external_cabinet(cabinet_name)
|
|
168
|
+
return nil if @msi_path.nil?
|
|
169
|
+
|
|
170
|
+
cab_path = File.join(File.dirname(@msi_path), cabinet_name)
|
|
171
|
+
|
|
172
|
+
begin
|
|
173
|
+
File.binread(cab_path) if File.exist?(cab_path)
|
|
174
|
+
rescue StandardError
|
|
175
|
+
nil
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|