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,141 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Copyright (C) 2025 Ribose Inc.
|
|
5
|
+
#
|
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a
|
|
7
|
+
# copy of this software and associated documentation files (the "Software"),
|
|
8
|
+
# to deal in the Software without restriction, including without limitation
|
|
9
|
+
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
10
|
+
# and/or sell copies of the Software, and to permit persons to whom the
|
|
11
|
+
# Software is furnished to do so, subject to the following conditions:
|
|
12
|
+
#
|
|
13
|
+
# The above copyright notice and this permission notice shall be included in
|
|
14
|
+
# all copies or substantial portions of the Software.
|
|
15
|
+
#
|
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
21
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
22
|
+
# DEALINGS IN THE SOFTWARE.
|
|
23
|
+
|
|
24
|
+
module Omnizip
|
|
25
|
+
# Abstract base class for all preprocessing filters
|
|
26
|
+
#
|
|
27
|
+
# Filters are reversible transformations applied to data before
|
|
28
|
+
# compression to improve compression ratios. This class defines the
|
|
29
|
+
# interface that all filter implementations must follow.
|
|
30
|
+
#
|
|
31
|
+
# The key innovation is format-aware ID resolution: different formats
|
|
32
|
+
# (7z, XZ) use different IDs for the same filter. This class provides the
|
|
33
|
+
# id_for_format(format) method to handle this mapping.
|
|
34
|
+
#
|
|
35
|
+
# @abstract Subclasses must implement encode, decode, metadata
|
|
36
|
+
#
|
|
37
|
+
# @example Create a custom filter
|
|
38
|
+
# class MyFilter < Filter
|
|
39
|
+
# def initialize(architecture:)
|
|
40
|
+
# super(architecture: architecture, name: "MyFilter")
|
|
41
|
+
# end
|
|
42
|
+
#
|
|
43
|
+
# def id_for_format(format)
|
|
44
|
+
# format == :xz ? 0x04 : 0x03
|
|
45
|
+
# end
|
|
46
|
+
#
|
|
47
|
+
# def encode(data, position = 0)
|
|
48
|
+
# # encoding logic
|
|
49
|
+
# end
|
|
50
|
+
#
|
|
51
|
+
# def decode(data, position = 0)
|
|
52
|
+
# # decoding logic
|
|
53
|
+
# end
|
|
54
|
+
#
|
|
55
|
+
# def self.metadata
|
|
56
|
+
# { name: "MyFilter", description: "..." }
|
|
57
|
+
# end
|
|
58
|
+
# end
|
|
59
|
+
class Filter
|
|
60
|
+
# @return [Symbol, nil] Architecture identifier (:x86, :arm, :arm64,
|
|
61
|
+
# :powerpc, :ia64, :sparc) or nil for architecture-agnostic filters
|
|
62
|
+
attr_reader :architecture
|
|
63
|
+
|
|
64
|
+
# @return [String] Human-readable filter name
|
|
65
|
+
attr_reader :name
|
|
66
|
+
|
|
67
|
+
# Initialize filter
|
|
68
|
+
#
|
|
69
|
+
# @param architecture [Symbol, nil] Target architecture (optional;
|
|
70
|
+
# filters that don't vary by architecture leave this as nil)
|
|
71
|
+
# @param name [String] Human-readable name
|
|
72
|
+
def initialize(architecture: nil, name: "Unknown")
|
|
73
|
+
@architecture = architecture
|
|
74
|
+
@name = name
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Get filter ID for specific format
|
|
78
|
+
#
|
|
79
|
+
# This is the KEY METHOD that solves the filter ID mapping problem.
|
|
80
|
+
# Different formats (7z, XZ) use different IDs for the same filter.
|
|
81
|
+
#
|
|
82
|
+
# @param format [Symbol] Format identifier (:seven_zip, :xz)
|
|
83
|
+
# @return [Integer] Format-specific filter ID
|
|
84
|
+
# @raise [NotImplementedError] Subclass must implement
|
|
85
|
+
#
|
|
86
|
+
# @example Get XZ format ID for BCJ filter
|
|
87
|
+
# bcj.id_for_format(:xz) # => 0x04
|
|
88
|
+
#
|
|
89
|
+
# @example Get 7z format ID for BCJ filter
|
|
90
|
+
# bcj.id_for_format(:seven_zip) # => 0x03030103
|
|
91
|
+
def id_for_format(format)
|
|
92
|
+
raise NotImplementedError,
|
|
93
|
+
"#{self.class} must implement #id_for_format(format)"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Encode (preprocess) data for compression
|
|
97
|
+
#
|
|
98
|
+
# Transforms data to make it more compressible. The transformation
|
|
99
|
+
# must be reversible - decode(encode(data)) == data.
|
|
100
|
+
#
|
|
101
|
+
# @param data [String] Binary data to encode
|
|
102
|
+
# @param position [Integer] Current stream position (default: 0)
|
|
103
|
+
# @return [String] Encoded binary data
|
|
104
|
+
# @raise [NotImplementedError] Subclass must implement
|
|
105
|
+
def encode(data, position = 0)
|
|
106
|
+
raise NotImplementedError,
|
|
107
|
+
"#{self.class} must implement #encode(data, position)"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Decode (postprocess) data after decompression
|
|
111
|
+
#
|
|
112
|
+
# Reverses the encoding transformation, restoring original data.
|
|
113
|
+
#
|
|
114
|
+
# @param data [String] Binary data to decode
|
|
115
|
+
# @param position [Integer] Current stream position (default: 0)
|
|
116
|
+
# @return [String] Decoded binary data
|
|
117
|
+
# @raise [NotImplementedError] Subclass must implement
|
|
118
|
+
def decode(data, position = 0)
|
|
119
|
+
raise NotImplementedError,
|
|
120
|
+
"#{self.class} must implement #decode(data, position)"
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
class << self
|
|
124
|
+
# Get metadata about this filter
|
|
125
|
+
#
|
|
126
|
+
# @return [Hash] Filter metadata
|
|
127
|
+
# @option metadata [String] :name Human-readable name
|
|
128
|
+
# @option metadata [String] :description Filter description
|
|
129
|
+
# @option metadata [Array<Symbol>] :supported_archs Supported architectures
|
|
130
|
+
# @raise [NotImplementedError] Subclass must implement
|
|
131
|
+
#
|
|
132
|
+
# @example Get BCJ filter metadata
|
|
133
|
+
# Omnizip::Filters::BCJ.metadata
|
|
134
|
+
# # => { name: "BCJ", description: "...", supported_archs: [:x86, :arm, ...] }
|
|
135
|
+
def metadata
|
|
136
|
+
raise NotImplementedError,
|
|
137
|
+
"#{self} must implement .metadata"
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Copyright (C) 2024 Ribose Inc.
|
|
5
|
+
#
|
|
6
|
+
# This file is part of Omnizip.
|
|
7
|
+
#
|
|
8
|
+
# Omnizip is a pure Ruby port of 7-Zip compression algorithms.
|
|
9
|
+
# Based on the 7-Zip LZMA SDK by Igor Pavlov.
|
|
10
|
+
#
|
|
11
|
+
# This library is free software; you can redistribute it and/or
|
|
12
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
13
|
+
# License as published by the Free Software Foundation; either
|
|
14
|
+
# version 2.1 of the License, or (at your option) any later version.
|
|
15
|
+
#
|
|
16
|
+
# See the COPYING file for the complete text of the license.
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
module Omnizip
|
|
20
|
+
# Pipeline for chaining multiple filters together.
|
|
21
|
+
#
|
|
22
|
+
# Filters are applied in sequence during encoding, and in reverse
|
|
23
|
+
# order during decoding. Position tracking is maintained across
|
|
24
|
+
# the entire pipeline.
|
|
25
|
+
class FilterPipeline
|
|
26
|
+
attr_reader :filters
|
|
27
|
+
|
|
28
|
+
# Initialize an empty filter pipeline.
|
|
29
|
+
def initialize
|
|
30
|
+
@filters = []
|
|
31
|
+
@position = 0
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Add a filter to the pipeline.
|
|
35
|
+
#
|
|
36
|
+
# Filters are applied in the order they are added during encoding,
|
|
37
|
+
# and in reverse order during decoding.
|
|
38
|
+
#
|
|
39
|
+
# @param filter [Omnizip::Filter] Filter instance to add
|
|
40
|
+
# @return [self] For method chaining
|
|
41
|
+
def add_filter(filter)
|
|
42
|
+
@filters << filter
|
|
43
|
+
self
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Check if pipeline has any filters.
|
|
47
|
+
#
|
|
48
|
+
# @return [Boolean] True if pipeline contains filters
|
|
49
|
+
def empty?
|
|
50
|
+
@filters.empty?
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Get number of filters in pipeline.
|
|
54
|
+
#
|
|
55
|
+
# @return [Integer] Number of filters
|
|
56
|
+
def size
|
|
57
|
+
@filters.size
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Encode (preprocess) data by applying all filters in order.
|
|
61
|
+
#
|
|
62
|
+
# Filters are applied sequentially with the same position value.
|
|
63
|
+
# Position represents the current stream position for address
|
|
64
|
+
# calculations.
|
|
65
|
+
#
|
|
66
|
+
# @param data [String] Binary data to encode
|
|
67
|
+
# @param position [Integer] Current stream position
|
|
68
|
+
# @return [String] Encoded binary data
|
|
69
|
+
def encode(data, position = 0)
|
|
70
|
+
return data.dup if @filters.empty?
|
|
71
|
+
|
|
72
|
+
result = data
|
|
73
|
+
@filters.each do |filter|
|
|
74
|
+
result = filter.encode(result, position)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
result
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Decode (postprocess) data by applying all filters in reverse order.
|
|
81
|
+
#
|
|
82
|
+
# Filters are applied in reverse order with the same position value
|
|
83
|
+
# to undo the encoding transformation.
|
|
84
|
+
#
|
|
85
|
+
# @param data [String] Binary data to decode
|
|
86
|
+
# @param position [Integer] Current stream position
|
|
87
|
+
# @return [String] Decoded binary data
|
|
88
|
+
def decode(data, position = 0)
|
|
89
|
+
return data.dup if @filters.empty?
|
|
90
|
+
|
|
91
|
+
result = data
|
|
92
|
+
# Apply filters in reverse order
|
|
93
|
+
@filters.reverse_each do |filter|
|
|
94
|
+
result = filter.decode(result, position)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
result
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Clear all filters from the pipeline.
|
|
101
|
+
#
|
|
102
|
+
# @return [void]
|
|
103
|
+
def clear
|
|
104
|
+
@filters.clear
|
|
105
|
+
@position = 0
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
class FilterRegistry < Omnizip::Registry
|
|
5
|
+
DEFAULT_FORMATS = %i[xz seven_zip].freeze
|
|
6
|
+
|
|
7
|
+
# Single source of truth for builtin filters. Each entry binds the
|
|
8
|
+
# filter name to its class and the formats that support it.
|
|
9
|
+
BUILTIN_FILTERS = {
|
|
10
|
+
"bcj-x86": { const: "Omnizip::Filters::BcjX86", formats: %i[xz seven_zip] },
|
|
11
|
+
"bcj-arm": { const: "Omnizip::Filters::BcjArm", formats: %i[xz seven_zip] },
|
|
12
|
+
"bcj-arm64": { const: "Omnizip::Filters::BcjArm64", formats: [:seven_zip] },
|
|
13
|
+
"bcj-ia64": { const: "Omnizip::Filters::BcjIa64", formats: %i[xz seven_zip] },
|
|
14
|
+
"bcj-ppc": { const: "Omnizip::Filters::BcjPpc", formats: %i[xz seven_zip] },
|
|
15
|
+
"bcj-sparc": { const: "Omnizip::Filters::BcjSparc", formats: %i[xz seven_zip] },
|
|
16
|
+
bcj: { const: "Omnizip::Filters::BCJ", formats: [:seven_zip] },
|
|
17
|
+
bcj2: { const: "Omnizip::Filters::Bcj2", formats: [:seven_zip] },
|
|
18
|
+
delta: { const: "Omnizip::Filters::Delta", formats: %i[xz seven_zip] },
|
|
19
|
+
}.freeze
|
|
20
|
+
|
|
21
|
+
class << self
|
|
22
|
+
def not_found_error_class
|
|
23
|
+
Omnizip::UnknownFilterError
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def label
|
|
27
|
+
"Filter"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def register(name, filter_class, formats: DEFAULT_FORMATS)
|
|
31
|
+
raise ArgumentError, "Filter name cannot be nil" if name.nil?
|
|
32
|
+
raise ArgumentError, "Filter class cannot be nil" if filter_class.nil?
|
|
33
|
+
|
|
34
|
+
synchronize do
|
|
35
|
+
storage[normalize_key(name)] = {
|
|
36
|
+
class: filter_class,
|
|
37
|
+
formats: formats,
|
|
38
|
+
}
|
|
39
|
+
end
|
|
40
|
+
filter_class
|
|
41
|
+
end
|
|
42
|
+
alias register_with_formats register
|
|
43
|
+
|
|
44
|
+
def get(name)
|
|
45
|
+
entry = entry_for(name)
|
|
46
|
+
unless entry
|
|
47
|
+
raise not_found_error_class,
|
|
48
|
+
"#{label} not registered: #{name.inspect}. " \
|
|
49
|
+
"Available: #{available.join(', ')}"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
entry[:class]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def get_for_format(name, format)
|
|
56
|
+
entry = entry_for(name)
|
|
57
|
+
raise KeyError, "Filter not found: #{name}" unless entry
|
|
58
|
+
|
|
59
|
+
unless entry[:formats].include?(format)
|
|
60
|
+
raise ArgumentError,
|
|
61
|
+
"Filter #{name} not supported for format #{format}"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
entry[:class].new
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def supports_format?(name, format)
|
|
68
|
+
entry = entry_for(name)
|
|
69
|
+
return false unless entry
|
|
70
|
+
|
|
71
|
+
entry[:formats]&.include?(format)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def filters_for_format(format)
|
|
75
|
+
# Ensure all lazy triggers have fired so the format filter list
|
|
76
|
+
# reflects every registered builtin.
|
|
77
|
+
lazy_triggers.keys.dup.each { |name| get(name) }
|
|
78
|
+
|
|
79
|
+
storage.select { |_, info| info[:formats]&.include?(format) }.keys
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
private
|
|
83
|
+
|
|
84
|
+
def entry_for(name)
|
|
85
|
+
# Reads hold the same mutex register writes under. The lazy
|
|
86
|
+
# trigger runs OUTSIDE the lock — it re-enters through
|
|
87
|
+
# register's own synchronize.
|
|
88
|
+
normalized = normalize_key(name)
|
|
89
|
+
entry = synchronize { storage[normalized] }
|
|
90
|
+
return entry if entry
|
|
91
|
+
|
|
92
|
+
trigger = synchronize { lazy_triggers[normalized] }
|
|
93
|
+
if trigger
|
|
94
|
+
trigger.call # outside the lock — it re-enters via register
|
|
95
|
+
return synchronize { storage[normalized] }
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
nil
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Lazy triggers — each trigger resolves the filter's class (firing
|
|
105
|
+
# autoload) and registers it with its declared formats. Idempotent:
|
|
106
|
+
# register overwrites the storage entry. Survives reset! because the
|
|
107
|
+
# trigger proc is held by FilterRegistry, not the storage.
|
|
108
|
+
Omnizip::FilterRegistry::BUILTIN_FILTERS.each do |name, spec|
|
|
109
|
+
Omnizip::FilterRegistry.register_lazy(name) do
|
|
110
|
+
klass = Object.const_get(spec[:const])
|
|
111
|
+
Omnizip::FilterRegistry.register(name, klass, formats: spec[:formats])
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Copyright (C) 2025 Ribose Inc.
|
|
5
|
+
#
|
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a
|
|
7
|
+
# copy of this software and associated documentation files (the "Software"),
|
|
8
|
+
# to deal in the Software without restriction, including without limitation
|
|
9
|
+
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
10
|
+
# and/or sell copies of the Software, and to permit persons to whom the
|
|
11
|
+
# Software is furnished to do so, subject to the following conditions:
|
|
12
|
+
#
|
|
13
|
+
# The above copyright notice and this permission notice shall be included in
|
|
14
|
+
# all copies or substantial portions of the Software.
|
|
15
|
+
#
|
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
21
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
22
|
+
# DEALINGS IN THE SOFTWARE.
|
|
23
|
+
|
|
24
|
+
module Omnizip
|
|
25
|
+
module Filters
|
|
26
|
+
# Unified BCJ (Branch/Call/Jump) filter for multiple architectures
|
|
27
|
+
#
|
|
28
|
+
# This filter preprocesses executable code by converting relative
|
|
29
|
+
# addresses in branch/call instructions to absolute addresses.
|
|
30
|
+
# The transformation is reversible and improves compression ratio.
|
|
31
|
+
#
|
|
32
|
+
# Supports x86, ARM, ARM Thumb, ARM64, PowerPC, IA64, SPARC architectures.
|
|
33
|
+
# Automatically returns correct filter ID for 7z or XZ format.
|
|
34
|
+
#
|
|
35
|
+
# @example Create x86 BCJ filter
|
|
36
|
+
# bcj = Omnizip::Filters::BCJ.new(architecture: :x86)
|
|
37
|
+
# bcj.id_for_format(:xz) # => 0x04
|
|
38
|
+
# bcj.id_for_format(:seven_zip) # => 0x03030103
|
|
39
|
+
class BCJ < ::Omnizip::Filter
|
|
40
|
+
# Architecture-specific configurations
|
|
41
|
+
CONFIG = {
|
|
42
|
+
x86: {
|
|
43
|
+
opcodes: [0xE8, 0xE9], # CALL, JMP
|
|
44
|
+
address_size: 4,
|
|
45
|
+
instruction_size: 5,
|
|
46
|
+
xz_id: 0x04,
|
|
47
|
+
seven_zip_id: 0x03030103,
|
|
48
|
+
},
|
|
49
|
+
arm: {
|
|
50
|
+
opcodes: [0x0A, 0x0B], # ARM BL/B conditional
|
|
51
|
+
address_size: 4,
|
|
52
|
+
instruction_size: 4,
|
|
53
|
+
xz_id: 0x07,
|
|
54
|
+
seven_zip_id: 0x03030501,
|
|
55
|
+
},
|
|
56
|
+
armthumb: {
|
|
57
|
+
opcodes: [0xE8, 0xF0, 0xF1], # ARM Thumb BL/B conditional
|
|
58
|
+
address_size: 4,
|
|
59
|
+
instruction_size: 4,
|
|
60
|
+
xz_id: 0x08,
|
|
61
|
+
seven_zip_id: 0x03030701,
|
|
62
|
+
},
|
|
63
|
+
arm64: {
|
|
64
|
+
opcodes: [0x00], # ARM64 BL
|
|
65
|
+
address_size: 4,
|
|
66
|
+
instruction_size: 4,
|
|
67
|
+
xz_id: nil, # Not yet in XZ
|
|
68
|
+
seven_zip_id: 0x03030601,
|
|
69
|
+
},
|
|
70
|
+
powerpc: {
|
|
71
|
+
opcodes: [0x48, 0x18], # PowerPC branch instructions
|
|
72
|
+
address_size: 4,
|
|
73
|
+
instruction_size: 4,
|
|
74
|
+
xz_id: 0x05,
|
|
75
|
+
seven_zip_id: 0x03030205,
|
|
76
|
+
},
|
|
77
|
+
ia64: {
|
|
78
|
+
opcodes: [0x04, 0x05, 0x06, 0x07, 0x08], # IA64 branches
|
|
79
|
+
address_size: 4,
|
|
80
|
+
instruction_size: 4,
|
|
81
|
+
xz_id: 0x06,
|
|
82
|
+
seven_zip_id: 0x03030401,
|
|
83
|
+
},
|
|
84
|
+
sparc: {
|
|
85
|
+
opcodes: [0x04, 0x06, 0x07], # SPARC call/branch
|
|
86
|
+
address_size: 4,
|
|
87
|
+
instruction_size: 4,
|
|
88
|
+
xz_id: 0x09,
|
|
89
|
+
seven_zip_id: 0x03030805,
|
|
90
|
+
},
|
|
91
|
+
}.freeze
|
|
92
|
+
|
|
93
|
+
# @return [Symbol] Architecture identifier
|
|
94
|
+
attr_reader :architecture
|
|
95
|
+
|
|
96
|
+
# Initialize BCJ filter for specific architecture
|
|
97
|
+
#
|
|
98
|
+
# @param architecture [Symbol] Target architecture (:x86, :arm, :armthumb, :arm64, :powerpc, :ia64, :sparc)
|
|
99
|
+
# @raise [ArgumentError] If architecture is not supported
|
|
100
|
+
def initialize(architecture:)
|
|
101
|
+
unless CONFIG.key?(architecture)
|
|
102
|
+
raise ArgumentError, "Unsupported BCJ architecture: #{architecture}. " \
|
|
103
|
+
"Supported: #{CONFIG.keys.join(', ')}"
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
@architecture = architecture
|
|
107
|
+
@config = CONFIG[architecture]
|
|
108
|
+
super(architecture: architecture, name: "BCJ-#{architecture.to_s.upcase}")
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Get filter ID for specific format
|
|
112
|
+
#
|
|
113
|
+
# @param format [Symbol] Format identifier (:seven_zip, :xz)
|
|
114
|
+
# @return [Integer] Format-specific filter ID
|
|
115
|
+
# @raise [ArgumentError] If format is not supported
|
|
116
|
+
# @raise [NotImplementedError] If architecture not supported in format
|
|
117
|
+
def id_for_format(format)
|
|
118
|
+
case format
|
|
119
|
+
when :seven_zip
|
|
120
|
+
@config[:seven_zip_id]
|
|
121
|
+
when :xz
|
|
122
|
+
id = @config[:xz_id]
|
|
123
|
+
if id.nil?
|
|
124
|
+
raise NotImplementedError,
|
|
125
|
+
"#{@architecture} BCJ not yet supported in XZ format"
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
id
|
|
129
|
+
else
|
|
130
|
+
raise ArgumentError,
|
|
131
|
+
"Unknown format: #{format}. Supported: :seven_zip, :xz"
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Encode (preprocess) data for compression
|
|
136
|
+
#
|
|
137
|
+
# Scans for branch/call opcodes and converts relative addresses
|
|
138
|
+
# to absolute addresses.
|
|
139
|
+
#
|
|
140
|
+
# @param data [String] Binary executable data
|
|
141
|
+
# @param position [Integer] Current stream position (default: 0)
|
|
142
|
+
# @return [String] Encoded binary data
|
|
143
|
+
def encode(data, position = 0)
|
|
144
|
+
return data.dup if data.bytesize < @config[:instruction_size]
|
|
145
|
+
|
|
146
|
+
result = data.b
|
|
147
|
+
i = 0
|
|
148
|
+
limit = data.bytesize - @config[:instruction_size]
|
|
149
|
+
|
|
150
|
+
while i <= limit
|
|
151
|
+
opcode = result.getbyte(i)
|
|
152
|
+
|
|
153
|
+
if @config[:opcodes].include?(opcode)
|
|
154
|
+
# Extract address (little-endian)
|
|
155
|
+
address = extract_address(result, i + 1)
|
|
156
|
+
|
|
157
|
+
# Check if valid relative address
|
|
158
|
+
if valid_relative_address?(address)
|
|
159
|
+
# Convert to absolute
|
|
160
|
+
absolute = address + position + i + @config[:instruction_size]
|
|
161
|
+
write_address(result, i + 1, absolute)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
i += @config[:instruction_size]
|
|
165
|
+
else
|
|
166
|
+
i += 1
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
result
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Decode (postprocess) data after decompression
|
|
174
|
+
#
|
|
175
|
+
# Reverses encoding by converting absolute addresses back to
|
|
176
|
+
# relative addresses.
|
|
177
|
+
#
|
|
178
|
+
# @param data [String] Binary executable data
|
|
179
|
+
# @param position [Integer] Current stream position (default: 0)
|
|
180
|
+
# @return [String] Decoded binary data
|
|
181
|
+
def decode(data, position = 0)
|
|
182
|
+
return data.dup if data.bytesize < @config[:instruction_size]
|
|
183
|
+
|
|
184
|
+
result = data.b
|
|
185
|
+
i = 0
|
|
186
|
+
limit = data.bytesize - @config[:instruction_size]
|
|
187
|
+
|
|
188
|
+
while i <= limit
|
|
189
|
+
opcode = result.getbyte(i)
|
|
190
|
+
|
|
191
|
+
if @config[:opcodes].include?(opcode)
|
|
192
|
+
# Extract absolute address
|
|
193
|
+
absolute = extract_address(result, i + 1)
|
|
194
|
+
|
|
195
|
+
# Convert to relative
|
|
196
|
+
address = absolute - (position + i + @config[:instruction_size])
|
|
197
|
+
|
|
198
|
+
if valid_relative_address?(address)
|
|
199
|
+
write_address(result, i + 1, address)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
i += @config[:instruction_size]
|
|
203
|
+
else
|
|
204
|
+
i += 1
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
result
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
class << self
|
|
212
|
+
# Get metadata about this filter
|
|
213
|
+
#
|
|
214
|
+
# @return [Hash] Filter metadata
|
|
215
|
+
def metadata
|
|
216
|
+
{
|
|
217
|
+
name: "BCJ",
|
|
218
|
+
description: "Branch/Call/Jump converter for executable files",
|
|
219
|
+
supported_architectures: CONFIG.keys,
|
|
220
|
+
architectures: {
|
|
221
|
+
x86: "x86/x86-64",
|
|
222
|
+
arm: "ARM 32-bit",
|
|
223
|
+
arm64: "ARM 64-bit",
|
|
224
|
+
powerpc: "PowerPC",
|
|
225
|
+
ia64: "IA-64 (Itanium)",
|
|
226
|
+
sparc: "SPARC",
|
|
227
|
+
},
|
|
228
|
+
}
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
private
|
|
233
|
+
|
|
234
|
+
# Extract address from data at offset (little-endian)
|
|
235
|
+
#
|
|
236
|
+
# @param data [String] Binary data
|
|
237
|
+
# @param offset [Integer] Starting position
|
|
238
|
+
# @return [Integer] Address value
|
|
239
|
+
def extract_address(data, offset)
|
|
240
|
+
bytes = data.byteslice(offset, @config[:address_size]).bytes
|
|
241
|
+
value = bytes.each_with_index.reduce(0) do |acc, (byte, i)|
|
|
242
|
+
acc | (byte << (8 * i))
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
# Convert to signed if needed (for 32-bit addresses)
|
|
246
|
+
mask = (1 << (8 * @config[:address_size])) - 1
|
|
247
|
+
value.nobits?(~mask) ? value - (1 << (8 * @config[:address_size])) : value
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# Write address to data at offset (little-endian)
|
|
251
|
+
#
|
|
252
|
+
# @param data [String] Binary data (modified in place)
|
|
253
|
+
# @param offset [Integer] Starting position
|
|
254
|
+
# @param value [Integer] Address value to write
|
|
255
|
+
# @return [void]
|
|
256
|
+
def write_address(data, offset, value)
|
|
257
|
+
@config[:address_size].times do |i|
|
|
258
|
+
data.setbyte(offset + i, value & 0xFF)
|
|
259
|
+
value >>= 8
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
# Check if address is a valid relative address
|
|
264
|
+
#
|
|
265
|
+
# Valid relative addresses have high byte of 0x00 or 0xFF,
|
|
266
|
+
# indicating small positive or negative offsets.
|
|
267
|
+
#
|
|
268
|
+
# @param value [Integer] Address value to check
|
|
269
|
+
# @return [Boolean] True if valid relative address
|
|
270
|
+
def valid_relative_address?(value)
|
|
271
|
+
unsigned = value & 0xFFFFFFFF
|
|
272
|
+
high_byte = (unsigned >> 24) & 0xFF
|
|
273
|
+
[0x00, 0xFF].include?(high_byte)
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Copyright (C) 2024 Ribose Inc.
|
|
5
|
+
#
|
|
6
|
+
# This file is part of Omnizip.
|
|
7
|
+
#
|
|
8
|
+
# Omnizip is a pure Ruby port of 7-Zip compression algorithms.
|
|
9
|
+
# Based on the 7-Zip LZMA SDK by Igor Pavlov.
|
|
10
|
+
#
|
|
11
|
+
# This library is free software; you can redistribute it and/or
|
|
12
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
13
|
+
# License as published by the Free Software Foundation; either
|
|
14
|
+
# version 2.1 of the License, or (at your option) any later version.
|
|
15
|
+
#
|
|
16
|
+
# See the COPYING file for the complete text of the license.
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
module Omnizip
|
|
20
|
+
module Filters
|
|
21
|
+
module Bcj2Constants
|
|
22
|
+
# Number of output streams
|
|
23
|
+
NUM_STREAMS = 4
|
|
24
|
+
|
|
25
|
+
# Stream indices
|
|
26
|
+
STREAM_MAIN = 0 # Main data stream (non-convertible bytes)
|
|
27
|
+
STREAM_CALL = 1 # CALL instruction addresses (E8)
|
|
28
|
+
STREAM_JUMP = 2 # JUMP instruction addresses (E9)
|
|
29
|
+
STREAM_RC = 3 # Range coder probability stream
|
|
30
|
+
|
|
31
|
+
# x86 opcodes
|
|
32
|
+
OPCODE_CALL = 0xE8 # CALL instruction
|
|
33
|
+
OPCODE_JUMP = 0xE9 # JUMP instruction
|
|
34
|
+
|
|
35
|
+
# Size of x86 address (4 bytes, little-endian)
|
|
36
|
+
ADDRESS_SIZE = 4
|
|
37
|
+
|
|
38
|
+
# Range coder constants
|
|
39
|
+
TOP_VALUE = 1 << 24 # Range normalization threshold
|
|
40
|
+
BIT_MODEL_TOTAL_BITS = 11 # Probability model bits
|
|
41
|
+
BIT_MODEL_TOTAL = 1 << BIT_MODEL_TOTAL_BITS
|
|
42
|
+
MOVE_BITS = 5 # Probability update shift
|
|
43
|
+
|
|
44
|
+
# Number of probability models (2 + 256)
|
|
45
|
+
# - 2 for general cases (not E8/E9, or 0F8x pattern)
|
|
46
|
+
# - 256 for byte-specific models when processing E8
|
|
47
|
+
NUM_PROBS = 2 + 256
|
|
48
|
+
|
|
49
|
+
# Initial probability value (50%)
|
|
50
|
+
INITIAL_PROB = BIT_MODEL_TOTAL >> 1
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|