omnizip 0.3.1
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 +754 -0
- data/COPYING +502 -0
- data/Gemfile +17 -0
- data/LICENSE +12 -0
- data/README.adoc +1045 -0
- data/Rakefile +12 -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 +91 -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 +271 -0
- data/docs/getting-started/index.adoc +42 -0
- data/docs/getting-started/installation.adoc +138 -0
- data/docs/getting-started/quick-start.adoc +185 -0
- data/docs/getting-started/your-first-archive.adoc +218 -0
- data/docs/guides/advanced-features/encryption.adoc +300 -0
- data/docs/guides/advanced-features/index.adoc +49 -0
- data/docs/guides/advanced-features/parallel-processing.adoc +246 -0
- data/docs/guides/advanced-features/progress-tracking.adoc +320 -0
- data/docs/guides/advanced-features/streaming.adoc +212 -0
- data/docs/guides/archive-formats/gzip-format.adoc +107 -0
- data/docs/guides/archive-formats/index.adoc +130 -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/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 +113 -0
- data/docs/guides/compression-algorithms/deflate.adoc +319 -0
- data/docs/guides/compression-algorithms/index.adoc +190 -0
- data/docs/guides/compression-algorithms/lzma.adoc +398 -0
- data/docs/guides/compression-algorithms/lzma2.adoc +327 -0
- data/docs/guides/compression-algorithms/ppmd.adoc +316 -0
- data/docs/guides/compression-algorithms/zstandard.adoc +361 -0
- data/docs/guides/creating-archives.adoc +354 -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 +218 -0
- data/docs/lychee.toml +67 -0
- data/docs/reference/api/overview.adoc +188 -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/troubleshooting/index.adoc +208 -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 +130 -0
- data/lib/omnizip/algorithm_registry.rb +86 -0
- data/lib/omnizip/algorithms/.keep +0 -0
- data/lib/omnizip/algorithms/bzip2/bwt.rb +225 -0
- data/lib/omnizip/algorithms/bzip2/decoder.rb +193 -0
- data/lib/omnizip/algorithms/bzip2/encoder.rb +237 -0
- data/lib/omnizip/algorithms/bzip2/huffman.rb +206 -0
- data/lib/omnizip/algorithms/bzip2/mtf.rb +101 -0
- data/lib/omnizip/algorithms/bzip2/rle.rb +151 -0
- data/lib/omnizip/algorithms/bzip2.rb +130 -0
- data/lib/omnizip/algorithms/deflate/constants.rb +28 -0
- data/lib/omnizip/algorithms/deflate/decoder.rb +38 -0
- data/lib/omnizip/algorithms/deflate/encoder.rb +46 -0
- data/lib/omnizip/algorithms/deflate.rb +128 -0
- data/lib/omnizip/algorithms/deflate64/constants.rb +45 -0
- data/lib/omnizip/algorithms/deflate64/decoder.rb +153 -0
- data/lib/omnizip/algorithms/deflate64/encoder.rb +98 -0
- data/lib/omnizip/algorithms/deflate64/huffman_coder.rb +354 -0
- data/lib/omnizip/algorithms/deflate64/lz77_encoder.rb +142 -0
- data/lib/omnizip/algorithms/deflate64.rb +109 -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 +148 -0
- data/lib/omnizip/algorithms/lzma/dictionary.rb +69 -0
- data/lib/omnizip/algorithms/lzma/distance_coder.rb +415 -0
- data/lib/omnizip/algorithms/lzma/encoder.rb +142 -0
- data/lib/omnizip/algorithms/lzma/length_coder.rb +260 -0
- data/lib/omnizip/algorithms/lzma/literal_decoder.rb +320 -0
- data/lib/omnizip/algorithms/lzma/literal_encoder.rb +210 -0
- data/lib/omnizip/algorithms/lzma/lzip_decoder.rb +341 -0
- data/lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb +192 -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 +205 -0
- data/lib/omnizip/algorithms/lzma/match_finder_config.rb +142 -0
- data/lib/omnizip/algorithms/lzma/match_finder_factory.rb +88 -0
- data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +130 -0
- data/lib/omnizip/algorithms/lzma/probability_models.rb +72 -0
- data/lib/omnizip/algorithms/lzma/range_coder.rb +85 -0
- data/lib/omnizip/algorithms/lzma/range_decoder.rb +434 -0
- data/lib/omnizip/algorithms/lzma/range_encoder.rb +194 -0
- data/lib/omnizip/algorithms/lzma/state.rb +127 -0
- data/lib/omnizip/algorithms/lzma/xz_buffered_range_encoder.rb +325 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder.rb +426 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder_fast.rb +645 -0
- data/lib/omnizip/algorithms/lzma/xz_match_finder_adapter.rb +227 -0
- data/lib/omnizip/algorithms/lzma/xz_price_calculator.rb +169 -0
- data/lib/omnizip/algorithms/lzma/xz_probability_models.rb +261 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder.rb +223 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder_exact.rb +331 -0
- data/lib/omnizip/algorithms/lzma/xz_state.rb +116 -0
- data/lib/omnizip/algorithms/lzma/xz_utils_decoder.rb +2055 -0
- data/lib/omnizip/algorithms/lzma.rb +238 -0
- data/lib/omnizip/algorithms/lzma2/chunk_manager.rb +182 -0
- data/lib/omnizip/algorithms/lzma2/constants.rb +41 -0
- data/lib/omnizip/algorithms/lzma2/encoder.rb +147 -0
- data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +161 -0
- data/lib/omnizip/algorithms/lzma2/properties.rb +179 -0
- data/lib/omnizip/algorithms/lzma2/simple_lzma2_encoder.rb +127 -0
- data/lib/omnizip/algorithms/lzma2/xz_encoder_adapter.rb +85 -0
- data/lib/omnizip/algorithms/lzma2.rb +141 -0
- data/lib/omnizip/algorithms/ppmd7/constants.rb +74 -0
- data/lib/omnizip/algorithms/ppmd7/context.rb +154 -0
- data/lib/omnizip/algorithms/ppmd7/decoder.rb +126 -0
- data/lib/omnizip/algorithms/ppmd7/encoder.rb +163 -0
- data/lib/omnizip/algorithms/ppmd7/model.rb +248 -0
- data/lib/omnizip/algorithms/ppmd7/symbol_state.rb +57 -0
- data/lib/omnizip/algorithms/ppmd7.rb +116 -0
- data/lib/omnizip/algorithms/ppmd8/constants.rb +61 -0
- data/lib/omnizip/algorithms/ppmd8/context.rb +34 -0
- data/lib/omnizip/algorithms/ppmd8/decoder.rb +107 -0
- data/lib/omnizip/algorithms/ppmd8/encoder.rb +138 -0
- data/lib/omnizip/algorithms/ppmd8/model.rb +250 -0
- data/lib/omnizip/algorithms/ppmd8/restoration_method.rb +78 -0
- data/lib/omnizip/algorithms/ppmd8.rb +82 -0
- data/lib/omnizip/algorithms/ppmd_base.rb +138 -0
- data/lib/omnizip/algorithms/sevenzip_lzma2.rb +123 -0
- data/lib/omnizip/algorithms/xz_lzma2.rb +118 -0
- data/lib/omnizip/algorithms/zstandard/constants.rb +25 -0
- data/lib/omnizip/algorithms/zstandard/decoder.rb +46 -0
- data/lib/omnizip/algorithms/zstandard/encoder.rb +51 -0
- data/lib/omnizip/algorithms/zstandard.rb +138 -0
- data/lib/omnizip/buffer/memory_archive.rb +251 -0
- data/lib/omnizip/buffer/memory_extractor.rb +224 -0
- data/lib/omnizip/buffer.rb +176 -0
- data/lib/omnizip/checksum_registry.rb +114 -0
- data/lib/omnizip/checksums/crc32.rb +100 -0
- data/lib/omnizip/checksums/crc64.rb +101 -0
- data/lib/omnizip/checksums/crc_base.rb +158 -0
- data/lib/omnizip/checksums/verifier.rb +131 -0
- data/lib/omnizip/chunked/memory_manager.rb +194 -0
- data/lib/omnizip/chunked/reader.rb +78 -0
- data/lib/omnizip/chunked/writer.rb +120 -0
- data/lib/omnizip/chunked.rb +129 -0
- data/lib/omnizip/cli/output_formatter.rb +104 -0
- data/lib/omnizip/cli.rb +572 -0
- data/lib/omnizip/commands/.keep +0 -0
- data/lib/omnizip/commands/archive_create_command.rb +427 -0
- data/lib/omnizip/commands/archive_extract_command.rb +272 -0
- data/lib/omnizip/commands/archive_list_command.rb +218 -0
- data/lib/omnizip/commands/archive_repair_command.rb +131 -0
- data/lib/omnizip/commands/archive_verify_command.rb +117 -0
- data/lib/omnizip/commands/compress_command.rb +117 -0
- data/lib/omnizip/commands/decompress_command.rb +120 -0
- data/lib/omnizip/commands/list_command.rb +53 -0
- data/lib/omnizip/commands/metadata_command.rb +153 -0
- data/lib/omnizip/commands/parity_create_command.rb +122 -0
- data/lib/omnizip/commands/parity_repair_command.rb +122 -0
- data/lib/omnizip/commands/parity_verify_command.rb +124 -0
- data/lib/omnizip/commands/profile_list_command.rb +56 -0
- data/lib/omnizip/commands/profile_show_command.rb +44 -0
- data/lib/omnizip/convenience.rb +359 -0
- data/lib/omnizip/converter/conversion_registry.rb +49 -0
- data/lib/omnizip/converter/conversion_strategy.rb +121 -0
- data/lib/omnizip/converter/seven_zip_to_zip_strategy.rb +97 -0
- data/lib/omnizip/converter/zip_to_seven_zip_strategy.rb +112 -0
- data/lib/omnizip/converter.rb +105 -0
- data/lib/omnizip/crypto/aes256/cipher.rb +100 -0
- data/lib/omnizip/crypto/aes256/constants.rb +28 -0
- data/lib/omnizip/crypto/aes256/key_derivation.rb +101 -0
- data/lib/omnizip/crypto/aes256.rb +102 -0
- data/lib/omnizip/error.rb +106 -0
- data/lib/omnizip/eta/exponential_smoothing_estimator.rb +98 -0
- data/lib/omnizip/eta/moving_average_estimator.rb +99 -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 +63 -0
- data/lib/omnizip/extraction/filter_chain.rb +177 -0
- data/lib/omnizip/extraction/glob_pattern.rb +140 -0
- data/lib/omnizip/extraction/pattern_matcher.rb +70 -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 +240 -0
- data/lib/omnizip/extraction.rb +111 -0
- data/lib/omnizip/file_type/mime_classifier.rb +144 -0
- data/lib/omnizip/file_type.rb +113 -0
- data/lib/omnizip/filter.rb +139 -0
- data/lib/omnizip/filter_pipeline.rb +108 -0
- data/lib/omnizip/filter_registry.rb +166 -0
- data/lib/omnizip/filters/bcj.rb +279 -0
- data/lib/omnizip/filters/bcj2/constants.rb +53 -0
- data/lib/omnizip/filters/bcj2/decoder.rb +200 -0
- data/lib/omnizip/filters/bcj2/encoder.rb +61 -0
- data/lib/omnizip/filters/bcj2/stream_data.rb +93 -0
- data/lib/omnizip/filters/bcj2.rb +99 -0
- data/lib/omnizip/filters/bcj_arm.rb +176 -0
- data/lib/omnizip/filters/bcj_arm64.rb +244 -0
- data/lib/omnizip/filters/bcj_ia64.rb +196 -0
- data/lib/omnizip/filters/bcj_ppc.rb +190 -0
- data/lib/omnizip/filters/bcj_sparc.rb +176 -0
- data/lib/omnizip/filters/bcj_x86.rb +193 -0
- data/lib/omnizip/filters/delta.rb +196 -0
- data/lib/omnizip/filters/filter_base.rb +72 -0
- data/lib/omnizip/filters/registry.rb +123 -0
- data/lib/omnizip/filters/xz_delta.rb +258 -0
- data/lib/omnizip/format_detector.rb +162 -0
- data/lib/omnizip/format_registry.rb +59 -0
- data/lib/omnizip/formats/.keep +0 -0
- data/lib/omnizip/formats/bzip2_file.rb +172 -0
- data/lib/omnizip/formats/cpio/constants.rb +55 -0
- data/lib/omnizip/formats/cpio/entry.rb +385 -0
- data/lib/omnizip/formats/cpio/reader.rb +196 -0
- data/lib/omnizip/formats/cpio/writer.rb +234 -0
- data/lib/omnizip/formats/cpio.rb +140 -0
- data/lib/omnizip/formats/format_spec_loader.rb +230 -0
- data/lib/omnizip/formats/gzip.rb +238 -0
- data/lib/omnizip/formats/iso/directory_builder.rb +297 -0
- data/lib/omnizip/formats/iso/directory_record.rb +152 -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 +197 -0
- data/lib/omnizip/formats/iso/rock_ridge.rb +349 -0
- data/lib/omnizip/formats/iso/volume_builder.rb +320 -0
- data/lib/omnizip/formats/iso/volume_descriptor.rb +168 -0
- data/lib/omnizip/formats/iso/writer.rb +530 -0
- data/lib/omnizip/formats/iso.rb +140 -0
- data/lib/omnizip/formats/lzip.rb +175 -0
- data/lib/omnizip/formats/lzma_alone.rb +171 -0
- data/lib/omnizip/formats/rar/archive_repairer.rb +243 -0
- data/lib/omnizip/formats/rar/archive_verifier.rb +195 -0
- data/lib/omnizip/formats/rar/block_parser.rb +243 -0
- data/lib/omnizip/formats/rar/compression/bit_stream.rb +180 -0
- data/lib/omnizip/formats/rar/compression/dispatcher.rb +217 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/decoder.rb +216 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/encoder.rb +158 -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/ppmd/context.rb +105 -0
- data/lib/omnizip/formats/rar/compression/ppmd/decoder.rb +219 -0
- data/lib/omnizip/formats/rar/compression/ppmd/encoder.rb +262 -0
- data/lib/omnizip/formats/rar/compression_method_registry.rb +106 -0
- data/lib/omnizip/formats/rar/constants.rb +82 -0
- data/lib/omnizip/formats/rar/decompressor.rb +238 -0
- data/lib/omnizip/formats/rar/external_writer.rb +312 -0
- data/lib/omnizip/formats/rar/header.rb +192 -0
- data/lib/omnizip/formats/rar/license_validator.rb +109 -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/parity_handler.rb +292 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzma.rb +202 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzss.rb +578 -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 +97 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_header.rb +114 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_manager.rb +166 -0
- data/lib/omnizip/formats/rar/rar5/encryption/key_derivation.rb +97 -0
- data/lib/omnizip/formats/rar/rar5/header.rb +187 -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 +264 -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 +194 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_encoder.rb +109 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_manager.rb +142 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_stream.rb +121 -0
- data/lib/omnizip/formats/rar/rar5/vint.rb +65 -0
- data/lib/omnizip/formats/rar/rar5/writer.rb +466 -0
- data/lib/omnizip/formats/rar/rar_format_base.rb +241 -0
- data/lib/omnizip/formats/rar/reader.rb +366 -0
- data/lib/omnizip/formats/rar/recovery_record.rb +245 -0
- data/lib/omnizip/formats/rar/volume_manager.rb +168 -0
- data/lib/omnizip/formats/rar/writer.rb +431 -0
- data/lib/omnizip/formats/rar.rb +205 -0
- data/lib/omnizip/formats/rar3/compressor.rb +73 -0
- data/lib/omnizip/formats/rar3/decompressor.rb +66 -0
- data/lib/omnizip/formats/rar3/reader.rb +386 -0
- data/lib/omnizip/formats/rar3/writer.rb +219 -0
- data/lib/omnizip/formats/rar5/compressor.rb +73 -0
- data/lib/omnizip/formats/rar5/decompressor.rb +66 -0
- data/lib/omnizip/formats/rar5/reader.rb +342 -0
- data/lib/omnizip/formats/rar5/writer.rb +214 -0
- data/lib/omnizip/formats/seven_zip/coder_chain.rb +150 -0
- data/lib/omnizip/formats/seven_zip/constants.rb +126 -0
- data/lib/omnizip/formats/seven_zip/encoded_header.rb +114 -0
- data/lib/omnizip/formats/seven_zip/encrypted_header.rb +142 -0
- data/lib/omnizip/formats/seven_zip/file_collector.rb +144 -0
- data/lib/omnizip/formats/seven_zip/header.rb +106 -0
- data/lib/omnizip/formats/seven_zip/header_encryptor.rb +134 -0
- data/lib/omnizip/formats/seven_zip/header_writer.rb +466 -0
- data/lib/omnizip/formats/seven_zip/models/coder_info.rb +30 -0
- data/lib/omnizip/formats/seven_zip/models/file_entry.rb +58 -0
- data/lib/omnizip/formats/seven_zip/models/folder.rb +69 -0
- data/lib/omnizip/formats/seven_zip/models/stream_info.rb +42 -0
- data/lib/omnizip/formats/seven_zip/parser.rb +660 -0
- data/lib/omnizip/formats/seven_zip/reader.rb +458 -0
- data/lib/omnizip/formats/seven_zip/split_archive_reader.rb +632 -0
- data/lib/omnizip/formats/seven_zip/split_archive_writer.rb +315 -0
- data/lib/omnizip/formats/seven_zip/stream_compressor.rb +151 -0
- data/lib/omnizip/formats/seven_zip/stream_decompressor.rb +162 -0
- data/lib/omnizip/formats/seven_zip/writer.rb +740 -0
- data/lib/omnizip/formats/seven_zip.rb +93 -0
- data/lib/omnizip/formats/tar/constants.rb +73 -0
- data/lib/omnizip/formats/tar/entry.rb +94 -0
- data/lib/omnizip/formats/tar/header.rb +168 -0
- data/lib/omnizip/formats/tar/reader.rb +121 -0
- data/lib/omnizip/formats/tar/writer.rb +216 -0
- data/lib/omnizip/formats/tar.rb +84 -0
- data/lib/omnizip/formats/xz/reader.rb +116 -0
- data/lib/omnizip/formats/xz.rb +237 -0
- data/lib/omnizip/formats/xz_impl/block_decoder.rb +754 -0
- data/lib/omnizip/formats/xz_impl/block_encoder.rb +306 -0
- data/lib/omnizip/formats/xz_impl/block_header.rb +210 -0
- data/lib/omnizip/formats/xz_impl/block_header_parser.rb +186 -0
- data/lib/omnizip/formats/xz_impl/constants.rb +49 -0
- data/lib/omnizip/formats/xz_impl/index_decoder.rb +174 -0
- data/lib/omnizip/formats/xz_impl/index_encoder.rb +122 -0
- data/lib/omnizip/formats/xz_impl/stream_decoder.rb +468 -0
- data/lib/omnizip/formats/xz_impl/stream_encoder.rb +99 -0
- data/lib/omnizip/formats/xz_impl/stream_footer.rb +81 -0
- data/lib/omnizip/formats/xz_impl/stream_footer_parser.rb +117 -0
- data/lib/omnizip/formats/xz_impl/stream_header.rb +55 -0
- data/lib/omnizip/formats/xz_impl/stream_header_parser.rb +108 -0
- data/lib/omnizip/formats/xz_impl/vli.rb +128 -0
- data/lib/omnizip/formats/xz_impl/writer.rb +421 -0
- data/lib/omnizip/formats/zip/central_directory_header.rb +195 -0
- data/lib/omnizip/formats/zip/constants.rb +69 -0
- data/lib/omnizip/formats/zip/end_of_central_directory.rb +133 -0
- data/lib/omnizip/formats/zip/local_file_header.rb +138 -0
- data/lib/omnizip/formats/zip/reader.rb +250 -0
- data/lib/omnizip/formats/zip/unix_extra_field.rb +153 -0
- data/lib/omnizip/formats/zip/writer.rb +375 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory.rb +104 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory_locator.rb +66 -0
- data/lib/omnizip/formats/zip/zip64_extra_field.rb +114 -0
- data/lib/omnizip/formats/zip.rb +50 -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/seven_zip/lzma/decoder.rb +421 -0
- data/lib/omnizip/implementations/seven_zip/lzma/encoder.rb +465 -0
- data/lib/omnizip/implementations/seven_zip/lzma/match_finder.rb +288 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb +200 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_encoder.rb +197 -0
- data/lib/omnizip/implementations/seven_zip/lzma/state_machine.rb +141 -0
- data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +519 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/decoder.rb +723 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +750 -0
- data/lib/omnizip/io/buffered_input.rb +146 -0
- data/lib/omnizip/io/buffered_output.rb +105 -0
- data/lib/omnizip/io/stream_manager.rb +115 -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 +124 -0
- data/lib/omnizip/metadata/archive_metadata.rb +114 -0
- data/lib/omnizip/metadata/entry_metadata.rb +146 -0
- data/lib/omnizip/metadata/metadata_editor.rb +171 -0
- data/lib/omnizip/metadata/metadata_registry.rb +64 -0
- data/lib/omnizip/metadata/metadata_validator.rb +99 -0
- data/lib/omnizip/metadata.rb +57 -0
- data/lib/omnizip/models/.keep +0 -0
- data/lib/omnizip/models/algorithm_metadata.rb +73 -0
- data/lib/omnizip/models/compression_options.rb +71 -0
- data/lib/omnizip/models/conversion_options.rb +87 -0
- data/lib/omnizip/models/conversion_result.rb +135 -0
- data/lib/omnizip/models/eta_result.rb +46 -0
- data/lib/omnizip/models/extraction_rule.rb +115 -0
- data/lib/omnizip/models/filter_chain.rb +144 -0
- data/lib/omnizip/models/filter_config.rb +183 -0
- data/lib/omnizip/models/match_result.rb +124 -0
- data/lib/omnizip/models/optimization_suggestion.rb +91 -0
- data/lib/omnizip/models/parallel_options.rb +104 -0
- data/lib/omnizip/models/performance_result.rb +79 -0
- data/lib/omnizip/models/profile_report.rb +82 -0
- data/lib/omnizip/models/progress_options.rb +38 -0
- data/lib/omnizip/models/split_options.rb +116 -0
- data/lib/omnizip/optimization_registry.rb +81 -0
- data/lib/omnizip/parallel/job_queue.rb +209 -0
- data/lib/omnizip/parallel/job_scheduler.rb +203 -0
- data/lib/omnizip/parallel/parallel_compressor.rb +347 -0
- data/lib/omnizip/parallel/parallel_extractor.rb +329 -0
- data/lib/omnizip/parallel/worker_pool.rb +223 -0
- data/lib/omnizip/parallel.rb +149 -0
- data/lib/omnizip/parity/chunked_block_processor.rb +196 -0
- data/lib/omnizip/parity/galois16.rb +145 -0
- data/lib/omnizip/parity/models/creator_packet.rb +73 -0
- data/lib/omnizip/parity/models/file_description_packet.rb +133 -0
- data/lib/omnizip/parity/models/ifsc_packet.rb +123 -0
- data/lib/omnizip/parity/models/main_packet.rb +128 -0
- data/lib/omnizip/parity/models/packet.rb +156 -0
- data/lib/omnizip/parity/models/packet_registry.rb +109 -0
- data/lib/omnizip/parity/models/recovery_slice_packet.rb +78 -0
- data/lib/omnizip/parity/par2_creator.rb +531 -0
- data/lib/omnizip/parity/par2_repairer.rb +407 -0
- data/lib/omnizip/parity/par2_verifier.rb +364 -0
- data/lib/omnizip/parity/par2cmdline_algorithm.rb +110 -0
- data/lib/omnizip/parity/par2cmdline_coefficients.rb +78 -0
- data/lib/omnizip/parity/reed_solomon_decoder.rb +266 -0
- data/lib/omnizip/parity/reed_solomon_encoder.rb +111 -0
- data/lib/omnizip/parity/reed_solomon_matrix.rb +342 -0
- data/lib/omnizip/parity.rb +186 -0
- data/lib/omnizip/password/encryption_registry.rb +65 -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 +192 -0
- data/lib/omnizip/password/zip_crypto_strategy.rb +141 -0
- data/lib/omnizip/password.rb +87 -0
- data/lib/omnizip/pipe/stream_compressor.rb +124 -0
- data/lib/omnizip/pipe/stream_decompressor.rb +174 -0
- data/lib/omnizip/pipe.rb +121 -0
- data/lib/omnizip/platform/ntfs_streams.rb +201 -0
- data/lib/omnizip/platform.rb +189 -0
- data/lib/omnizip/profile/archive_profile.rb +39 -0
- data/lib/omnizip/profile/balanced_profile.rb +33 -0
- data/lib/omnizip/profile/binary_profile.rb +36 -0
- data/lib/omnizip/profile/compression_profile.rb +158 -0
- data/lib/omnizip/profile/custom_profile.rb +157 -0
- data/lib/omnizip/profile/fast_profile.rb +33 -0
- data/lib/omnizip/profile/maximum_profile.rb +33 -0
- data/lib/omnizip/profile/profile_detector.rb +110 -0
- data/lib/omnizip/profile/profile_registry.rb +161 -0
- data/lib/omnizip/profile/text_profile.rb +36 -0
- data/lib/omnizip/profile.rb +190 -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 +169 -0
- data/lib/omnizip/profiler.rb +204 -0
- data/lib/omnizip/progress/callback_reporter.rb +36 -0
- data/lib/omnizip/progress/console_reporter.rb +62 -0
- data/lib/omnizip/progress/log_reporter.rb +91 -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 +190 -0
- data/lib/omnizip/progress/silent_reporter.rb +24 -0
- data/lib/omnizip/progress.rb +127 -0
- data/lib/omnizip/rubyzip_compat.rb +63 -0
- data/lib/omnizip/temp/safe_extract.rb +168 -0
- data/lib/omnizip/temp/temp_file.rb +124 -0
- data/lib/omnizip/temp/temp_file_pool.rb +109 -0
- data/lib/omnizip/temp.rb +181 -0
- data/lib/omnizip/version.rb +5 -0
- data/lib/omnizip/zip/entry.rb +156 -0
- data/lib/omnizip/zip/file.rb +485 -0
- data/lib/omnizip/zip/input_stream.rb +273 -0
- data/lib/omnizip/zip/output_stream.rb +324 -0
- data/lib/omnizip.rb +156 -0
- data/readme-docs/advanced-features.adoc +515 -0
- data/readme-docs/api-usage.adoc +444 -0
- data/readme-docs/architecture.adoc +449 -0
- data/readme-docs/archive-formats.adoc +479 -0
- data/readme-docs/cli-usage.adoc +222 -0
- data/readme-docs/compression-algorithms.adoc +442 -0
- data/readme-docs/compression-profiles.adoc +247 -0
- data/readme-docs/encryption-checksums.adoc +328 -0
- data/readme-docs/format-converter.adoc +325 -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/xz-file-format-1.2.1.txt +1174 -0
- metadata +617 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "constants"
|
|
4
|
+
require_relative "../../algorithm_registry"
|
|
5
|
+
require_relative "../../filter_registry"
|
|
6
|
+
require_relative "../../filter_pipeline"
|
|
7
|
+
|
|
8
|
+
module Omnizip
|
|
9
|
+
module Formats
|
|
10
|
+
module SevenZip
|
|
11
|
+
# Builds coder chains from .7z folder specifications
|
|
12
|
+
# Maps method IDs to algorithms and filters, reconstructing the
|
|
13
|
+
# decompression pipeline
|
|
14
|
+
class CoderChain
|
|
15
|
+
include Constants
|
|
16
|
+
|
|
17
|
+
# Build coder chain from folder specification
|
|
18
|
+
#
|
|
19
|
+
# @param folder [Models::Folder] Folder specification
|
|
20
|
+
# @return [Hash] Coder chain configuration
|
|
21
|
+
# @raise [RuntimeError] if unsupported method encountered
|
|
22
|
+
def self.build_from_folder(folder)
|
|
23
|
+
return nil if folder.coders.empty?
|
|
24
|
+
|
|
25
|
+
# For now, support single coder or coder+filter combinations
|
|
26
|
+
main_coder = folder.coders.last
|
|
27
|
+
algorithm = algorithm_for_method(main_coder.method_id)
|
|
28
|
+
|
|
29
|
+
# Check for filters
|
|
30
|
+
filters = []
|
|
31
|
+
if folder.coders.size > 1
|
|
32
|
+
folder.coders[0..-2].each do |coder|
|
|
33
|
+
filter = filter_for_method(coder.method_id)
|
|
34
|
+
filters << filter if filter
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
{
|
|
39
|
+
algorithm: algorithm,
|
|
40
|
+
filters: filters,
|
|
41
|
+
properties: main_coder.properties,
|
|
42
|
+
unpack_size: folder.unpack_sizes.last,
|
|
43
|
+
}
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Map method ID to algorithm
|
|
47
|
+
#
|
|
48
|
+
# @param method_id [Integer] Method ID from .7z file
|
|
49
|
+
# @return [Symbol] Algorithm identifier
|
|
50
|
+
# @raise [RuntimeError] if method not supported
|
|
51
|
+
def self.algorithm_for_method(method_id)
|
|
52
|
+
case method_id
|
|
53
|
+
when MethodId::COPY
|
|
54
|
+
nil # No decompression needed
|
|
55
|
+
when MethodId::LZMA
|
|
56
|
+
:lzma
|
|
57
|
+
when MethodId::LZMA2
|
|
58
|
+
:lzma2
|
|
59
|
+
when MethodId::PPMD
|
|
60
|
+
:ppmd7
|
|
61
|
+
when MethodId::BZIP2
|
|
62
|
+
:bzip2
|
|
63
|
+
when MethodId::DEFLATE
|
|
64
|
+
:deflate
|
|
65
|
+
when MethodId::DEFLATE64
|
|
66
|
+
:deflate64
|
|
67
|
+
else
|
|
68
|
+
raise "Unsupported compression method: " \
|
|
69
|
+
"0x#{method_id.to_s(16)}"
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Map method ID to filter
|
|
74
|
+
#
|
|
75
|
+
# @param method_id [Integer] Method ID from .7z file
|
|
76
|
+
# @return [Symbol, nil] Filter identifier or nil
|
|
77
|
+
def self.filter_for_method(method_id)
|
|
78
|
+
case method_id
|
|
79
|
+
when FilterId::BCJ_X86
|
|
80
|
+
:bcj_x86
|
|
81
|
+
when FilterId::BCJ_PPC
|
|
82
|
+
:bcj_ppc
|
|
83
|
+
when FilterId::BCJ_IA64
|
|
84
|
+
:bcj_ia64
|
|
85
|
+
when FilterId::BCJ_ARM
|
|
86
|
+
:bcj_arm
|
|
87
|
+
when FilterId::BCJ_ARMT
|
|
88
|
+
:bcj_armt
|
|
89
|
+
when FilterId::BCJ_SPARC
|
|
90
|
+
:bcj_sparc
|
|
91
|
+
when FilterId::ARM64
|
|
92
|
+
:bcj_arm64
|
|
93
|
+
when FilterId::DELTA
|
|
94
|
+
:delta
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Create decompressor for coder chain
|
|
99
|
+
#
|
|
100
|
+
# @param chain_config [Hash] Chain configuration
|
|
101
|
+
# @param input_io [IO] Input stream
|
|
102
|
+
# @return [Object] Decompressor instance
|
|
103
|
+
def self.create_decompressor(chain_config, input_io)
|
|
104
|
+
return nil unless chain_config
|
|
105
|
+
return input_io unless chain_config[:algorithm]
|
|
106
|
+
|
|
107
|
+
# Get algorithm
|
|
108
|
+
algo_class = AlgorithmRegistry.get(chain_config[:algorithm])
|
|
109
|
+
unless algo_class
|
|
110
|
+
raise "Algorithm not found: #{chain_config[:algorithm]}"
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Create algorithm instance
|
|
114
|
+
decompressor = algo_class.new
|
|
115
|
+
# Pass properties if algorithm supports them
|
|
116
|
+
# Some algorithms (LZMA2) need properties
|
|
117
|
+
if chain_config[:properties] && !chain_config[:properties].empty? && decompressor.respond_to?(:properties=)
|
|
118
|
+
decompressor.properties = chain_config[:properties]
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Apply filters if present
|
|
122
|
+
if chain_config[:filters] && !chain_config[:filters].empty?
|
|
123
|
+
# Build filter pipeline
|
|
124
|
+
pipeline = FilterPipeline.new
|
|
125
|
+
chain_config[:filters].each do |filter_sym|
|
|
126
|
+
filter_class = FilterRegistry.get(filter_sym)
|
|
127
|
+
raise "Filter not found: #{filter_sym}" unless filter_class
|
|
128
|
+
|
|
129
|
+
pipeline.add_filter(filter_class.new)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Return composite: input -> algorithm -> filters
|
|
133
|
+
{
|
|
134
|
+
decompressor: decompressor,
|
|
135
|
+
pipeline: pipeline,
|
|
136
|
+
input: input_io,
|
|
137
|
+
}
|
|
138
|
+
else
|
|
139
|
+
# Just algorithm
|
|
140
|
+
{
|
|
141
|
+
decompressor: decompressor,
|
|
142
|
+
pipeline: nil,
|
|
143
|
+
input: input_io,
|
|
144
|
+
}
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Formats
|
|
5
|
+
module SevenZip
|
|
6
|
+
# Constants for .7z archive format
|
|
7
|
+
# Based on 7-Zip specification
|
|
8
|
+
module Constants
|
|
9
|
+
# Archive signature and header
|
|
10
|
+
SIGNATURE = "7z\xBC\xAF\x27\x1C".b.freeze
|
|
11
|
+
SIGNATURE_SIZE = 6
|
|
12
|
+
START_HEADER_SIZE = 32 # 0x20
|
|
13
|
+
MAJOR_VERSION = 0
|
|
14
|
+
MINOR_VERSION = 4
|
|
15
|
+
|
|
16
|
+
# Property IDs for .7z format structure
|
|
17
|
+
module PropertyId
|
|
18
|
+
K_END = 0x00
|
|
19
|
+
HEADER = 0x01
|
|
20
|
+
ARCHIVE_PROPERTIES = 0x02
|
|
21
|
+
ADDITIONAL_STREAMS_INFO = 0x03
|
|
22
|
+
MAIN_STREAMS_INFO = 0x04
|
|
23
|
+
FILES_INFO = 0x05
|
|
24
|
+
PACK_INFO = 0x06
|
|
25
|
+
UNPACK_INFO = 0x07
|
|
26
|
+
SUBSTREAMS_INFO = 0x08
|
|
27
|
+
SIZE = 0x09
|
|
28
|
+
CRC = 0x0A
|
|
29
|
+
FOLDER = 0x0B
|
|
30
|
+
CODERS_UNPACK_SIZE = 0x0C
|
|
31
|
+
NUM_UNPACK_STREAM = 0x0D
|
|
32
|
+
EMPTY_STREAM = 0x0E
|
|
33
|
+
EMPTY_FILE = 0x0F
|
|
34
|
+
ANTI = 0x10
|
|
35
|
+
NAME = 0x11
|
|
36
|
+
CTIME = 0x12
|
|
37
|
+
ATIME = 0x13
|
|
38
|
+
MTIME = 0x14
|
|
39
|
+
WIN_ATTRIB = 0x15
|
|
40
|
+
COMMENT = 0x16
|
|
41
|
+
ENCODED_HEADER = 0x17
|
|
42
|
+
START_POS = 0x18
|
|
43
|
+
DUMMY = 0x19
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Method IDs for compression algorithms
|
|
47
|
+
module MethodId
|
|
48
|
+
# Compression methods
|
|
49
|
+
COPY = 0x00
|
|
50
|
+
LZMA = 0x030101
|
|
51
|
+
LZMA2 = 0x21
|
|
52
|
+
PPMD = 0x030401
|
|
53
|
+
BZIP2 = 0x040202
|
|
54
|
+
DEFLATE = 0x040108
|
|
55
|
+
DEFLATE64 = 0x040109
|
|
56
|
+
|
|
57
|
+
# Crypto methods
|
|
58
|
+
AES = 0x06F10701
|
|
59
|
+
|
|
60
|
+
def self.name(id)
|
|
61
|
+
case id
|
|
62
|
+
when COPY then "Copy"
|
|
63
|
+
when LZMA then "LZMA"
|
|
64
|
+
when LZMA2 then "LZMA2"
|
|
65
|
+
when PPMD then "PPMd"
|
|
66
|
+
when BZIP2 then "BZip2"
|
|
67
|
+
when DEFLATE then "Deflate"
|
|
68
|
+
when DEFLATE64 then "Deflate64"
|
|
69
|
+
when AES then "AES256"
|
|
70
|
+
else "Unknown(0x#{id.to_s(16)})"
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Filter IDs
|
|
76
|
+
module FilterId
|
|
77
|
+
# BCJ filters for executable files
|
|
78
|
+
BCJ_X86 = 0x03030103
|
|
79
|
+
BCJ_PPC = 0x03030205
|
|
80
|
+
BCJ_IA64 = 0x03030401
|
|
81
|
+
BCJ_ARM = 0x03030501
|
|
82
|
+
BCJ_ARMT = 0x03030701
|
|
83
|
+
BCJ_SPARC = 0x03030805
|
|
84
|
+
ARM64 = 0x03030601
|
|
85
|
+
|
|
86
|
+
# BCJ2 filter
|
|
87
|
+
BCJ2 = 0x03030111
|
|
88
|
+
|
|
89
|
+
# Swap filters for byte order conversion
|
|
90
|
+
SWAP2 = 0x03030204
|
|
91
|
+
SWAP4 = 0x03030208
|
|
92
|
+
|
|
93
|
+
# Delta filter
|
|
94
|
+
DELTA = 0x03
|
|
95
|
+
|
|
96
|
+
def self.name(id)
|
|
97
|
+
case id
|
|
98
|
+
when BCJ_X86 then "BCJ-x86"
|
|
99
|
+
when BCJ_PPC then "BCJ-PPC"
|
|
100
|
+
when BCJ_IA64 then "BCJ-IA64"
|
|
101
|
+
when BCJ_ARM then "BCJ-ARM"
|
|
102
|
+
when BCJ_ARMT then "BCJ-ARMT"
|
|
103
|
+
when BCJ_SPARC then "BCJ-SPARC"
|
|
104
|
+
when DELTA then "Delta"
|
|
105
|
+
when ARM64 then "BCJ-ARM64"
|
|
106
|
+
when BCJ2 then "BCJ2"
|
|
107
|
+
when SWAP2 then "Swap2"
|
|
108
|
+
when SWAP4 then "Swap4"
|
|
109
|
+
else "Unknown(0x#{id.to_s(16)})"
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def self.bcj_filter?(id)
|
|
114
|
+
[BCJ_X86, BCJ_PPC, BCJ_IA64, BCJ_ARM, BCJ_ARMT, BCJ_SPARC,
|
|
115
|
+
ARM64].include?(id)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Maximum limits
|
|
120
|
+
MAX_NUM_CODERS = 4
|
|
121
|
+
MAX_NUM_BONDS = 3
|
|
122
|
+
MAX_NUM_PACK_STREAMS = 4
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "constants"
|
|
4
|
+
require_relative "../../algorithms/lzma2"
|
|
5
|
+
require_relative "../../checksums/crc32"
|
|
6
|
+
|
|
7
|
+
module Omnizip
|
|
8
|
+
module Formats
|
|
9
|
+
module SevenZip
|
|
10
|
+
# Handles 7-Zip encoded headers
|
|
11
|
+
#
|
|
12
|
+
# 7-Zip can compress the Next Header metadata with LZMA2 to save space.
|
|
13
|
+
# This module provides functionality to encode and decode headers.
|
|
14
|
+
module EncodedHeader
|
|
15
|
+
include Constants
|
|
16
|
+
|
|
17
|
+
module_function
|
|
18
|
+
|
|
19
|
+
# Encode next header with LZMA2 compression
|
|
20
|
+
#
|
|
21
|
+
# @param header_data [String] Uncompressed header data
|
|
22
|
+
# @return [String] Encoded header property with compressed data
|
|
23
|
+
def encode(header_data)
|
|
24
|
+
# Compress header with LZMA2
|
|
25
|
+
compressed = compress_header(header_data)
|
|
26
|
+
|
|
27
|
+
# Build encoded header property
|
|
28
|
+
encoded = String.new(encoding: "BINARY")
|
|
29
|
+
encoded << [PropertyId::ENCODED_HEADER].pack("C")
|
|
30
|
+
|
|
31
|
+
# Write pack info for compressed header
|
|
32
|
+
encoded << [PropertyId::PACK_INFO].pack("C")
|
|
33
|
+
encoded << encode_uint64(0) # Pack position
|
|
34
|
+
encoded << encode_uint64(1) # Number of pack streams
|
|
35
|
+
|
|
36
|
+
# Write size
|
|
37
|
+
encoded << [PropertyId::SIZE].pack("C")
|
|
38
|
+
encoded << encode_uint64(compressed.bytesize)
|
|
39
|
+
|
|
40
|
+
encoded << [PropertyId::K_END].pack("C")
|
|
41
|
+
|
|
42
|
+
# Write coder info (LZMA2)
|
|
43
|
+
encoded << [PropertyId::UNPACK_INFO].pack("C")
|
|
44
|
+
encoded << [PropertyId::FOLDER].pack("C")
|
|
45
|
+
encoded << encode_uint64(1) # Number of folders
|
|
46
|
+
encoded << [0].pack("C") # External flag (0 = inline)
|
|
47
|
+
|
|
48
|
+
# Number of coders
|
|
49
|
+
encoded << encode_uint64(1)
|
|
50
|
+
|
|
51
|
+
# Coder info for LZMA2
|
|
52
|
+
# Method ID: LZMA2 = 0x21
|
|
53
|
+
encoded << [1].pack("C") # Main byte (1 byte for ID, no properties)
|
|
54
|
+
encoded << [0x21].pack("C") # LZMA2 method ID
|
|
55
|
+
|
|
56
|
+
# Unpack size
|
|
57
|
+
encoded << [PropertyId::CODERS_UNPACK_SIZE].pack("C")
|
|
58
|
+
encoded << encode_uint64(header_data.bytesize)
|
|
59
|
+
|
|
60
|
+
encoded << [PropertyId::K_END].pack("C")
|
|
61
|
+
|
|
62
|
+
# Append compressed data
|
|
63
|
+
encoded << compressed
|
|
64
|
+
|
|
65
|
+
encoded
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Compress header data with LZMA2
|
|
69
|
+
#
|
|
70
|
+
# @param header_data [String] Uncompressed header
|
|
71
|
+
# @return [String] Compressed header
|
|
72
|
+
def compress_header(header_data)
|
|
73
|
+
# Use 7-Zip SDK LZMA2 encoder for 7-Zip format
|
|
74
|
+
encoder = Omnizip::Implementations::SevenZip::LZMA2::Encoder.new(
|
|
75
|
+
dict_size: 4096, # Small dictionary for headers
|
|
76
|
+
lc: 3,
|
|
77
|
+
lp: 0,
|
|
78
|
+
pb: 2,
|
|
79
|
+
standalone: false, # No property byte
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
encoder.encode(header_data)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Encode unsigned 64-bit integer in 7-Zip variable-length format
|
|
86
|
+
#
|
|
87
|
+
# @param value [Integer] Value to encode
|
|
88
|
+
# @return [String] Encoded bytes
|
|
89
|
+
def encode_uint64(value)
|
|
90
|
+
return [value].pack("C") if value < 0x80
|
|
91
|
+
|
|
92
|
+
result = String.new(encoding: "BINARY")
|
|
93
|
+
shift = 0
|
|
94
|
+
|
|
95
|
+
loop do
|
|
96
|
+
byte = value & 0x7F
|
|
97
|
+
value >>= 7
|
|
98
|
+
|
|
99
|
+
if value.zero?
|
|
100
|
+
result << [byte].pack("C")
|
|
101
|
+
break
|
|
102
|
+
else
|
|
103
|
+
result << [byte | 0x80].pack("C")
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
shift += 7
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
result
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "constants"
|
|
4
|
+
|
|
5
|
+
module Omnizip
|
|
6
|
+
module Formats
|
|
7
|
+
module SevenZip
|
|
8
|
+
# Encrypted header model for .7z archives
|
|
9
|
+
# Stores metadata for header encryption
|
|
10
|
+
class EncryptedHeader
|
|
11
|
+
include Constants
|
|
12
|
+
|
|
13
|
+
attr_accessor :encrypted_data, :salt, :iv, :original_size, :crc
|
|
14
|
+
|
|
15
|
+
# Initialize encrypted header
|
|
16
|
+
#
|
|
17
|
+
# @param encrypted_data [String] Encrypted header bytes
|
|
18
|
+
# @param salt [String] PBKDF2 salt
|
|
19
|
+
# @param iv [String] AES initialization vector
|
|
20
|
+
# @param original_size [Integer] Size before encryption
|
|
21
|
+
# @param crc [Integer, nil] CRC32 of encrypted data (optional)
|
|
22
|
+
def initialize(encrypted_data: nil, salt: nil, iv: nil,
|
|
23
|
+
original_size: 0, crc: nil)
|
|
24
|
+
@encrypted_data = encrypted_data
|
|
25
|
+
@salt = salt
|
|
26
|
+
@iv = iv
|
|
27
|
+
@original_size = original_size
|
|
28
|
+
@crc = crc
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Serialize encrypted header to binary format
|
|
32
|
+
#
|
|
33
|
+
# Format:
|
|
34
|
+
# - 1 byte: PropertyId::ENCODED_HEADER marker
|
|
35
|
+
# - 8 bytes: Encrypted data size (little-endian)
|
|
36
|
+
# - 16 bytes: Salt
|
|
37
|
+
# - 16 bytes: IV
|
|
38
|
+
# - 8 bytes: Original size (little-endian)
|
|
39
|
+
# - 4 bytes: CRC32 (optional, 0 if not set)
|
|
40
|
+
# - N bytes: Encrypted data
|
|
41
|
+
#
|
|
42
|
+
# @return [String] Binary representation
|
|
43
|
+
def to_binary
|
|
44
|
+
data = String.new(encoding: "BINARY")
|
|
45
|
+
|
|
46
|
+
# Marker for encoded header
|
|
47
|
+
data << [PropertyId::ENCODED_HEADER].pack("C")
|
|
48
|
+
|
|
49
|
+
# Encrypted data size
|
|
50
|
+
data << [@encrypted_data.bytesize].pack("Q<")
|
|
51
|
+
|
|
52
|
+
# Encryption parameters
|
|
53
|
+
data << @salt
|
|
54
|
+
data << @iv
|
|
55
|
+
|
|
56
|
+
# Original size
|
|
57
|
+
data << [@original_size].pack("Q<")
|
|
58
|
+
|
|
59
|
+
# CRC (0 if not set)
|
|
60
|
+
data << [crc || 0].pack("V")
|
|
61
|
+
|
|
62
|
+
# Encrypted data
|
|
63
|
+
data << @encrypted_data
|
|
64
|
+
|
|
65
|
+
data
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Parse encrypted header from binary data
|
|
69
|
+
#
|
|
70
|
+
# @param data [String] Binary data
|
|
71
|
+
# @return [EncryptedHeader] Parsed header
|
|
72
|
+
# @raise [RuntimeError] if data is invalid
|
|
73
|
+
def self.from_binary(data)
|
|
74
|
+
raise "Invalid encrypted header: too short" if data.bytesize < 54
|
|
75
|
+
|
|
76
|
+
pos = 0
|
|
77
|
+
|
|
78
|
+
# Check marker
|
|
79
|
+
marker = data.getbyte(pos)
|
|
80
|
+
pos += 1
|
|
81
|
+
unless marker == PropertyId::ENCODED_HEADER
|
|
82
|
+
raise "Invalid encrypted header marker: expected #{PropertyId::ENCODED_HEADER}, got #{marker}"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Read encrypted data size
|
|
86
|
+
encrypted_size = data[pos, 8].unpack1("Q<")
|
|
87
|
+
pos += 8
|
|
88
|
+
|
|
89
|
+
# Read salt
|
|
90
|
+
salt = data[pos, 16]
|
|
91
|
+
pos += 16
|
|
92
|
+
|
|
93
|
+
# Read IV
|
|
94
|
+
iv = data[pos, 16]
|
|
95
|
+
pos += 16
|
|
96
|
+
|
|
97
|
+
# Read original size
|
|
98
|
+
original_size = data[pos, 8].unpack1("Q<")
|
|
99
|
+
pos += 8
|
|
100
|
+
|
|
101
|
+
# Read CRC
|
|
102
|
+
crc = data[pos, 4].unpack1("V")
|
|
103
|
+
pos += 4
|
|
104
|
+
|
|
105
|
+
# Read encrypted data
|
|
106
|
+
encrypted_data = data[pos, encrypted_size]
|
|
107
|
+
|
|
108
|
+
new(
|
|
109
|
+
encrypted_data: encrypted_data,
|
|
110
|
+
salt: salt,
|
|
111
|
+
iv: iv,
|
|
112
|
+
original_size: original_size,
|
|
113
|
+
crc: crc.zero? ? nil : crc,
|
|
114
|
+
)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Check if header is valid
|
|
118
|
+
#
|
|
119
|
+
# @return [Boolean] true if has all required fields
|
|
120
|
+
def valid?
|
|
121
|
+
!@encrypted_data.nil? &&
|
|
122
|
+
!@salt.nil? &&
|
|
123
|
+
!@iv.nil? &&
|
|
124
|
+
@original_size.positive? &&
|
|
125
|
+
@encrypted_data.bytesize.positive?
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Verify CRC if set
|
|
129
|
+
#
|
|
130
|
+
# @return [Boolean] true if CRC matches or not set
|
|
131
|
+
def verify_crc
|
|
132
|
+
return true if @crc.nil?
|
|
133
|
+
|
|
134
|
+
require_relative "../../checksums/crc32"
|
|
135
|
+
calc_crc = Omnizip::Checksums::Crc32.new
|
|
136
|
+
calc_crc.update(@encrypted_data)
|
|
137
|
+
calc_crc.value == @crc
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require_relative "models/file_entry"
|
|
5
|
+
|
|
6
|
+
module Omnizip
|
|
7
|
+
module Formats
|
|
8
|
+
module SevenZip
|
|
9
|
+
# Collects files and directories for archiving
|
|
10
|
+
# Handles file metadata, timestamps, and attributes
|
|
11
|
+
class FileCollector
|
|
12
|
+
attr_reader :entries
|
|
13
|
+
|
|
14
|
+
# Initialize collector
|
|
15
|
+
def initialize
|
|
16
|
+
@entries = []
|
|
17
|
+
@base_path = nil
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Add path (file or directory) to collection
|
|
21
|
+
#
|
|
22
|
+
# @param path [String] Path to file or directory
|
|
23
|
+
# @param archive_path [String, nil] Path in archive (nil = auto)
|
|
24
|
+
# @param recursive [Boolean] Recursively add directories
|
|
25
|
+
def add_path(path, archive_path: nil, recursive: true)
|
|
26
|
+
path = File.expand_path(path)
|
|
27
|
+
raise "Path not found: #{path}" unless File.exist?(path)
|
|
28
|
+
|
|
29
|
+
@base_path ||= File.dirname(path)
|
|
30
|
+
|
|
31
|
+
if File.directory?(path)
|
|
32
|
+
add_directory(path, archive_path, recursive)
|
|
33
|
+
else
|
|
34
|
+
add_file(path, archive_path)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Add files matching glob pattern
|
|
39
|
+
#
|
|
40
|
+
# @param pattern [String] Glob pattern
|
|
41
|
+
# @param base_path [String, nil] Base path for relative names
|
|
42
|
+
def add_glob(pattern, base_path: nil)
|
|
43
|
+
@base_path ||= base_path || Dir.pwd
|
|
44
|
+
|
|
45
|
+
Dir.glob(pattern).each do |path|
|
|
46
|
+
add_path(path)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Get collected file entries
|
|
51
|
+
#
|
|
52
|
+
# @return [Array<Models::FileEntry>] File entries
|
|
53
|
+
def collect_files
|
|
54
|
+
@entries.sort_by(&:name)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
# Add single file
|
|
60
|
+
#
|
|
61
|
+
# @param file_path [String] Full path to file
|
|
62
|
+
# @param archive_path [String, nil] Path in archive
|
|
63
|
+
def add_file(file_path, archive_path)
|
|
64
|
+
archive_name = archive_path || relative_path(file_path)
|
|
65
|
+
|
|
66
|
+
entry = Models::FileEntry.new.tap do |e|
|
|
67
|
+
e.name = archive_name
|
|
68
|
+
e.size = File.size(file_path)
|
|
69
|
+
e.has_stream = e.size.positive?
|
|
70
|
+
e.is_dir = false
|
|
71
|
+
e.mtime = File.mtime(file_path)
|
|
72
|
+
e.attributes = file_attributes(file_path)
|
|
73
|
+
e.source_path = file_path
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
@entries << entry
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Add directory and optionally its contents
|
|
80
|
+
#
|
|
81
|
+
# @param dir_path [String] Directory path
|
|
82
|
+
# @param archive_path [String, nil] Path in archive
|
|
83
|
+
# @param recursive [Boolean] Add contents recursively
|
|
84
|
+
def add_directory(dir_path, archive_path, recursive)
|
|
85
|
+
archive_name = archive_path || relative_path(dir_path)
|
|
86
|
+
archive_name += "/" unless archive_name.end_with?("/")
|
|
87
|
+
|
|
88
|
+
# Add directory entry
|
|
89
|
+
entry = Models::FileEntry.new.tap do |e|
|
|
90
|
+
e.name = archive_name
|
|
91
|
+
e.size = 0
|
|
92
|
+
e.has_stream = false
|
|
93
|
+
e.is_dir = true
|
|
94
|
+
e.mtime = File.mtime(dir_path)
|
|
95
|
+
e.attributes = file_attributes(dir_path)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
@entries << entry
|
|
99
|
+
|
|
100
|
+
return unless recursive
|
|
101
|
+
|
|
102
|
+
# Add contents
|
|
103
|
+
Dir.each_child(dir_path) do |child|
|
|
104
|
+
child_path = File.join(dir_path, child)
|
|
105
|
+
add_path(child_path, archive_path: nil, recursive: true)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Get relative path for archive
|
|
110
|
+
#
|
|
111
|
+
# @param path [String] Full path
|
|
112
|
+
# @return [String] Relative path
|
|
113
|
+
def relative_path(path)
|
|
114
|
+
if @base_path && path.start_with?(@base_path)
|
|
115
|
+
path[@base_path.length..].sub(%r{^/}, "")
|
|
116
|
+
else
|
|
117
|
+
File.basename(path)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Get file attributes (Unix permissions as Windows attributes)
|
|
122
|
+
#
|
|
123
|
+
# @param path [String] File path
|
|
124
|
+
# @return [Integer] Attribute flags
|
|
125
|
+
def file_attributes(path)
|
|
126
|
+
attrs = 0
|
|
127
|
+
stat = File.stat(path)
|
|
128
|
+
|
|
129
|
+
# Windows FILE_ATTRIBUTE_DIRECTORY = 0x10
|
|
130
|
+
attrs |= 0x10 if stat.directory?
|
|
131
|
+
|
|
132
|
+
# Windows FILE_ATTRIBUTE_ARCHIVE = 0x20
|
|
133
|
+
attrs |= 0x20 unless stat.directory?
|
|
134
|
+
|
|
135
|
+
# Convert Unix permissions to Windows read-only flag
|
|
136
|
+
# FILE_ATTRIBUTE_READONLY = 0x01
|
|
137
|
+
attrs |= 0x01 unless stat.writable?
|
|
138
|
+
|
|
139
|
+
attrs
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|