omnizip 0.4.7-x86_64-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,437 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "zlib"
|
|
5
|
+
require "stringio"
|
|
6
|
+
require "tmpdir"
|
|
7
|
+
|
|
8
|
+
module Omnizip
|
|
9
|
+
module Formats
|
|
10
|
+
module Rar
|
|
11
|
+
# Pure Ruby RAR archive writer
|
|
12
|
+
#
|
|
13
|
+
# Writes RAR 1.5-4.x ("RAR4") archives per the on-disk layout
|
|
14
|
+
# unrar accepts: HEAD_CRC holds the low 16 bits of a CRC32 over
|
|
15
|
+
# the header bytes that follow it, HEAD_SIZE counts the whole
|
|
16
|
+
# block including the CRC field, and the 7-byte signature is
|
|
17
|
+
# itself the marker block (no second marker follows).
|
|
18
|
+
#
|
|
19
|
+
# Only METHOD_STORE output is interoperable with official RAR
|
|
20
|
+
# tools; the LZ/PPMd encoders produce Omnizip-internal streams
|
|
21
|
+
# that Omnizip can read back but unrar cannot.
|
|
22
|
+
#
|
|
23
|
+
# @example Create a RAR archive
|
|
24
|
+
# writer = Writer.new('archive.rar')
|
|
25
|
+
# writer.add_file('document.pdf')
|
|
26
|
+
# writer.add_directory('photos/')
|
|
27
|
+
# writer.write
|
|
28
|
+
#
|
|
29
|
+
# @example Create with options
|
|
30
|
+
# writer = Writer.new('archive.rar',
|
|
31
|
+
# compression: :best
|
|
32
|
+
# )
|
|
33
|
+
class Writer
|
|
34
|
+
include Omnizip::Formats::Rar::Constants
|
|
35
|
+
|
|
36
|
+
# @return [String] Output archive path
|
|
37
|
+
attr_reader :output_path
|
|
38
|
+
|
|
39
|
+
# @return [Hash] Compression options
|
|
40
|
+
attr_reader :options
|
|
41
|
+
|
|
42
|
+
# @return [Array<Hash>] Files to add
|
|
43
|
+
attr_reader :files
|
|
44
|
+
|
|
45
|
+
# @return [Array<Hash>] Directories to add
|
|
46
|
+
attr_reader :directories
|
|
47
|
+
|
|
48
|
+
# Check if RAR creation is available
|
|
49
|
+
#
|
|
50
|
+
# @return [Boolean] always true for pure Ruby implementation
|
|
51
|
+
def self.available?
|
|
52
|
+
true
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Get RAR writer information
|
|
56
|
+
#
|
|
57
|
+
# @return [Hash] Writer type and version
|
|
58
|
+
def self.info
|
|
59
|
+
{
|
|
60
|
+
available: true,
|
|
61
|
+
type: :pure_ruby,
|
|
62
|
+
version: "4.0",
|
|
63
|
+
}
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Initialize RAR writer
|
|
67
|
+
#
|
|
68
|
+
# @param output_path [String] Output RAR file path
|
|
69
|
+
# @param options [Hash] Compression options
|
|
70
|
+
# @option options [Symbol] :compression Compression level
|
|
71
|
+
# (:store, :fastest, :fast, :normal, :good, :best)
|
|
72
|
+
# @option options [Boolean] :solid Create solid archive
|
|
73
|
+
# (not implemented; ignored with a warning)
|
|
74
|
+
# @option options [Integer] :recovery Recovery record
|
|
75
|
+
# percentage (not implemented; ignored with a warning)
|
|
76
|
+
# @option options [String] :password Archive password
|
|
77
|
+
# (RAR4 encryption is not implemented)
|
|
78
|
+
# @option options [Integer] :volume_size Split into volumes
|
|
79
|
+
# (not implemented; ignored with a warning)
|
|
80
|
+
# @option options [Boolean] :test_after_create Test archive after creation
|
|
81
|
+
# @raise [NotImplementedError] if :password or :encrypt_headers is given
|
|
82
|
+
def initialize(output_path, options = {})
|
|
83
|
+
@output_path = output_path
|
|
84
|
+
@options = default_options.merge(options)
|
|
85
|
+
@files = []
|
|
86
|
+
@directories = []
|
|
87
|
+
|
|
88
|
+
if @options[:password] || @options[:encrypt_headers]
|
|
89
|
+
raise NotImplementedError,
|
|
90
|
+
"RAR4 encryption is not implemented"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
warn_unimplemented_options
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Add a name-only directory entry (empty trees survive
|
|
97
|
+
# archive creation instead of vanishing)
|
|
98
|
+
#
|
|
99
|
+
# @param archive_path [String] Directory path inside the
|
|
100
|
+
# archive (trailing slash optional)
|
|
101
|
+
# @return [self]
|
|
102
|
+
def add_directory_entry(archive_path)
|
|
103
|
+
@files << {
|
|
104
|
+
source: nil,
|
|
105
|
+
archive_path: archive_path.chomp("/"),
|
|
106
|
+
directory: true,
|
|
107
|
+
}
|
|
108
|
+
self
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Add file to archive
|
|
112
|
+
#
|
|
113
|
+
# @param file_path [String] Path to file
|
|
114
|
+
# @param archive_path [String, nil] Path within archive
|
|
115
|
+
# @raise [ArgumentError] if file does not exist
|
|
116
|
+
def add_file(file_path, archive_path = nil)
|
|
117
|
+
raise ArgumentError, "File not found: #{file_path}" unless
|
|
118
|
+
File.exist?(file_path)
|
|
119
|
+
|
|
120
|
+
@files << {
|
|
121
|
+
source: File.expand_path(file_path),
|
|
122
|
+
archive_path: archive_path,
|
|
123
|
+
}
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Add directory to archive
|
|
127
|
+
#
|
|
128
|
+
# @param dir_path [String] Path to directory
|
|
129
|
+
# @param recursive [Boolean] Include subdirectories
|
|
130
|
+
# @param archive_path [String, nil] Path within archive
|
|
131
|
+
# @raise [ArgumentError] if directory does not exist
|
|
132
|
+
def add_directory(dir_path, recursive: true, archive_path: nil)
|
|
133
|
+
raise ArgumentError, "Directory not found: #{dir_path}" unless
|
|
134
|
+
Dir.exist?(dir_path)
|
|
135
|
+
|
|
136
|
+
@directories << {
|
|
137
|
+
source: File.expand_path(dir_path),
|
|
138
|
+
recursive: recursive,
|
|
139
|
+
archive_path: archive_path,
|
|
140
|
+
}
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Create RAR archive
|
|
144
|
+
#
|
|
145
|
+
# @return [String] Path to created archive
|
|
146
|
+
def write
|
|
147
|
+
File.open(@output_path, "wb") do |io|
|
|
148
|
+
write_signature(io)
|
|
149
|
+
write_archive_header(io)
|
|
150
|
+
write_file_entries(io)
|
|
151
|
+
write_end_block(io)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
test_archive if @options[:test_after_create]
|
|
155
|
+
|
|
156
|
+
@output_path
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
private
|
|
160
|
+
|
|
161
|
+
# Default compression options
|
|
162
|
+
#
|
|
163
|
+
# @return [Hash] Default options
|
|
164
|
+
def default_options
|
|
165
|
+
{
|
|
166
|
+
compression: :normal,
|
|
167
|
+
solid: false,
|
|
168
|
+
recovery: 0,
|
|
169
|
+
encrypt_headers: false,
|
|
170
|
+
password: nil,
|
|
171
|
+
volume_size: nil,
|
|
172
|
+
test_after_create: false,
|
|
173
|
+
}
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# Warn about accepted-but-unimplemented options so the
|
|
177
|
+
# resulting archive never advertises features it lacks.
|
|
178
|
+
def warn_unimplemented_options
|
|
179
|
+
if @options[:solid]
|
|
180
|
+
warn "RAR4 writer ignores solid: not implemented " \
|
|
181
|
+
"(no corresponding flag is written)"
|
|
182
|
+
end
|
|
183
|
+
if @options[:volume_size]
|
|
184
|
+
warn "RAR4 writer ignores volume_size: not implemented " \
|
|
185
|
+
"(no corresponding flag is written)"
|
|
186
|
+
end
|
|
187
|
+
recovery = @options[:recovery]
|
|
188
|
+
return unless recovery.is_a?(Numeric) && recovery.positive?
|
|
189
|
+
return if recovery == true
|
|
190
|
+
|
|
191
|
+
warn "RAR4 writer ignores recovery: not implemented " \
|
|
192
|
+
"(no corresponding flag is written)"
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# RAR4 HEAD_CRC: low 16 bits of the CRC32 over every header
|
|
196
|
+
# byte that follows the 2-byte CRC field (unrar archive.cpp).
|
|
197
|
+
#
|
|
198
|
+
# @param header_data [String] Header bytes after the CRC field
|
|
199
|
+
# @return [Integer] 16-bit CRC value
|
|
200
|
+
def calculate_header_crc(header_data)
|
|
201
|
+
Zlib.crc32(header_data) & 0xFFFF
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Convert Ruby Time to DOS time format
|
|
205
|
+
#
|
|
206
|
+
# @param time [Time] Ruby time object
|
|
207
|
+
# @return [Integer] DOS time format (32-bit)
|
|
208
|
+
def dos_time(time)
|
|
209
|
+
dos_date = ((time.year - 1980) << 9) | (time.month << 5) | time.day
|
|
210
|
+
dos_time_part = (time.hour << 11) | (time.min << 5) | (time.sec / 2)
|
|
211
|
+
(dos_date << 16) | dos_time_part
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# Write RAR signature (the marker block itself)
|
|
215
|
+
#
|
|
216
|
+
# @param io [IO] Output stream
|
|
217
|
+
def write_signature(io)
|
|
218
|
+
io.write(RAR4_SIGNATURE.pack("C*"))
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# Write archive header (MAIN_HEAD, 13 bytes total)
|
|
222
|
+
#
|
|
223
|
+
# @param io [IO] Output stream
|
|
224
|
+
def write_archive_header(io)
|
|
225
|
+
header_data = [BLOCK_ARCHIVE].pack("C") +
|
|
226
|
+
[0x0000].pack("v") + # HEAD_FLAGS
|
|
227
|
+
[0x000D].pack("v") + # HEAD_SIZE
|
|
228
|
+
[0].pack("v") + [0].pack("V") # HighPosAV, PosAV
|
|
229
|
+
|
|
230
|
+
io.write([calculate_header_crc(header_data)].pack("v"))
|
|
231
|
+
io.write(header_data)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# Write file entries
|
|
235
|
+
#
|
|
236
|
+
# @param io [IO] Output stream
|
|
237
|
+
def write_file_entries(io)
|
|
238
|
+
@directories.each do |dir_info|
|
|
239
|
+
write_directory_entries(io, dir_info)
|
|
240
|
+
end
|
|
241
|
+
@files.each do |file_info|
|
|
242
|
+
write_file_entry(io, file_info)
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
# Write a single file entry
|
|
247
|
+
#
|
|
248
|
+
# @param io [IO] Output stream
|
|
249
|
+
# @param file_info [Hash] File information
|
|
250
|
+
def write_file_entry(io, file_info)
|
|
251
|
+
file_path = file_info[:source]
|
|
252
|
+
archive_path = file_info[:archive_path] || File.basename(file_path)
|
|
253
|
+
directory = file_info[:directory] || false
|
|
254
|
+
|
|
255
|
+
file_data = directory ? "" : File.binread(file_path)
|
|
256
|
+
|
|
257
|
+
method = file_info[:method] ||
|
|
258
|
+
(directory ? METHOD_STORE : select_compression_method(file_data))
|
|
259
|
+
compressed_data = compress_data(file_data, method)
|
|
260
|
+
|
|
261
|
+
if directory && file_path.nil?
|
|
262
|
+
# Name-only directory entry: no source to stat
|
|
263
|
+
file_attr = 0o040755
|
|
264
|
+
file_time = dos_time(Time.now)
|
|
265
|
+
data_crc = 0
|
|
266
|
+
else
|
|
267
|
+
stat = File.stat(file_path)
|
|
268
|
+
file_attr = directory ? 0o040755 : stat.mode
|
|
269
|
+
file_time = dos_time(stat.mtime)
|
|
270
|
+
data_crc = Zlib.crc32(file_data)
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
name_bytes = archive_path.encode("UTF-8").bytes
|
|
274
|
+
|
|
275
|
+
# HEAD_FLAGS bit 0x8000 (LONG_BLOCK) marks a data area of
|
|
276
|
+
# PACK_SIZE bytes; the full dictionary mask 0xE0 marks
|
|
277
|
+
# directory entries (a directory has no dictionary) —
|
|
278
|
+
# confirmed against unrar extraction behavior.
|
|
279
|
+
flags = BLOCK_LONG
|
|
280
|
+
flags |= FILE_DIRECTORY if directory
|
|
281
|
+
flags |= FILE_LARGE if file_data.bytesize > 0xFFFFFFFF
|
|
282
|
+
|
|
283
|
+
# Fixed fields after HEAD_SIZE: PACK(4) + UNP(4) + HOST_OS(1)
|
|
284
|
+
# + FILE_CRC(4) + FTIME(4) + UNP_VER(1) + METHOD(1) +
|
|
285
|
+
# NAME_SIZE(2) + ATTR(4) = 25 bytes; plus TYPE(1) +
|
|
286
|
+
# FLAGS(2) + SIZE(2) and the 2-byte CRC itself.
|
|
287
|
+
header_size = 32 + name_bytes.size
|
|
288
|
+
header_size += 8 if flags.anybits?(FILE_LARGE)
|
|
289
|
+
|
|
290
|
+
header_data = [BLOCK_FILE].pack("C") +
|
|
291
|
+
[flags].pack("v") +
|
|
292
|
+
[header_size].pack("v") +
|
|
293
|
+
[compressed_data.bytesize & 0xFFFFFFFF].pack("V") +
|
|
294
|
+
[file_data.bytesize & 0xFFFFFFFF].pack("V") +
|
|
295
|
+
[OS_UNIX].pack("C") +
|
|
296
|
+
[data_crc].pack("V") +
|
|
297
|
+
[file_time].pack("V") +
|
|
298
|
+
[compression_version(method)].pack("C") +
|
|
299
|
+
[method].pack("C") +
|
|
300
|
+
[name_bytes.size].pack("v") +
|
|
301
|
+
[file_attr].pack("V")
|
|
302
|
+
|
|
303
|
+
if flags.anybits?(FILE_LARGE)
|
|
304
|
+
header_data += [(compressed_data.bytesize >> 32) & 0xFFFFFFFF].pack("V")
|
|
305
|
+
header_data += [(file_data.bytesize >> 32) & 0xFFFFFFFF].pack("V")
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
header_data += name_bytes.pack("C*")
|
|
309
|
+
|
|
310
|
+
io.write([calculate_header_crc(header_data)].pack("v"))
|
|
311
|
+
io.write(header_data)
|
|
312
|
+
io.write(compressed_data)
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
# Write directory tree as explicit directory entries plus the
|
|
316
|
+
# files inside them
|
|
317
|
+
#
|
|
318
|
+
# @param io [IO] Output stream
|
|
319
|
+
# @param dir_info [Hash] Directory information
|
|
320
|
+
def write_directory_entries(io, dir_info)
|
|
321
|
+
dir_path = dir_info[:source]
|
|
322
|
+
prefix = dir_info[:archive_path].to_s.gsub(%r{^/+|/+$}, "")
|
|
323
|
+
|
|
324
|
+
pattern = dir_info[:recursive] ? File.join(dir_path, "**", "*") : File.join(dir_path, "*")
|
|
325
|
+
Dir.glob(pattern).each do |path|
|
|
326
|
+
relative = path.delete_prefix("#{dir_path}/")
|
|
327
|
+
name = prefix.empty? ? relative : "#{prefix}/#{relative}"
|
|
328
|
+
|
|
329
|
+
if File.directory?(path)
|
|
330
|
+
write_file_entry(io, {
|
|
331
|
+
source: path,
|
|
332
|
+
archive_path: name,
|
|
333
|
+
directory: true,
|
|
334
|
+
})
|
|
335
|
+
else
|
|
336
|
+
write_file_entry(io, {
|
|
337
|
+
source: path,
|
|
338
|
+
archive_path: name,
|
|
339
|
+
})
|
|
340
|
+
end
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
# Write end block (ENDARC, 7 bytes total)
|
|
345
|
+
#
|
|
346
|
+
# @param io [IO] Output stream
|
|
347
|
+
def write_end_block(io)
|
|
348
|
+
header_data = [BLOCK_ENDARC].pack("C") +
|
|
349
|
+
[0x0000].pack("v") +
|
|
350
|
+
[0x0007].pack("v")
|
|
351
|
+
|
|
352
|
+
io.write([calculate_header_crc(header_data)].pack("v"))
|
|
353
|
+
io.write(header_data)
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
# Compress data using native RAR compression
|
|
357
|
+
#
|
|
358
|
+
# @param data [String] Data to compress
|
|
359
|
+
# @param method [Integer] RAR compression method (default: METHOD_NORMAL)
|
|
360
|
+
# @return [String] Compressed data
|
|
361
|
+
def compress_data(data, method = METHOD_NORMAL)
|
|
362
|
+
input = StringIO.new(data)
|
|
363
|
+
output = StringIO.new
|
|
364
|
+
|
|
365
|
+
Compression::Dispatcher.compress(method, input, output, @options)
|
|
366
|
+
|
|
367
|
+
output.string
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
# Select appropriate compression method based on data
|
|
371
|
+
#
|
|
372
|
+
# @param data [String] Data to compress
|
|
373
|
+
# @return [Integer] RAR compression method code
|
|
374
|
+
def select_compression_method(data)
|
|
375
|
+
# Small files: use METHOD_STORE to avoid Huffman tree overhead (258 bytes)
|
|
376
|
+
return METHOD_STORE if data.size < 300
|
|
377
|
+
|
|
378
|
+
# User-specified compression level takes precedence
|
|
379
|
+
case @options[:compression]
|
|
380
|
+
when :store
|
|
381
|
+
METHOD_STORE
|
|
382
|
+
when :fastest
|
|
383
|
+
METHOD_FASTEST
|
|
384
|
+
when :fast
|
|
385
|
+
METHOD_FAST
|
|
386
|
+
when :normal
|
|
387
|
+
METHOD_NORMAL
|
|
388
|
+
when :good
|
|
389
|
+
METHOD_GOOD
|
|
390
|
+
when :best
|
|
391
|
+
METHOD_BEST
|
|
392
|
+
else
|
|
393
|
+
# Default based on compression level option if numeric
|
|
394
|
+
if @options[:level] == 9
|
|
395
|
+
METHOD_BEST # PPMd for maximum compression
|
|
396
|
+
else
|
|
397
|
+
METHOD_NORMAL # LZ77+Huffman default
|
|
398
|
+
end
|
|
399
|
+
end
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
# Get compression version needed to extract. WinRAR writes 20
|
|
403
|
+
# for stored files and 29 for every compressed method,
|
|
404
|
+
# including PPMd (method 0x35) — confirmed against libarchive
|
|
405
|
+
# RAR4 fixtures created by the official tool.
|
|
406
|
+
#
|
|
407
|
+
# @param method [Integer] Compression method
|
|
408
|
+
# @return [Integer] Version code
|
|
409
|
+
def compression_version(method)
|
|
410
|
+
method == METHOD_STORE ? 20 : 29
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
# Test archive integrity by reading it back with the RAR
|
|
414
|
+
# reader and comparing every extracted entry to its source
|
|
415
|
+
#
|
|
416
|
+
# @return [Boolean] true if valid
|
|
417
|
+
def test_archive
|
|
418
|
+
return false unless File.exist?(@output_path)
|
|
419
|
+
|
|
420
|
+
reader = Reader.new(@output_path)
|
|
421
|
+
reader.open
|
|
422
|
+
|
|
423
|
+
Dir.mktmpdir("omnizip_rar_test") do |tmp|
|
|
424
|
+
@files.map { |f| f[:archive_path] || File.basename(f[:source]) }
|
|
425
|
+
.zip(@files.map { |f| f[:source] }).all? do |name, source|
|
|
426
|
+
dest = File.join(tmp, name)
|
|
427
|
+
reader.extract_entry(name, dest)
|
|
428
|
+
FileUtils.compare_file(source, dest)
|
|
429
|
+
end
|
|
430
|
+
end
|
|
431
|
+
rescue StandardError
|
|
432
|
+
false
|
|
433
|
+
end
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
end
|
|
437
|
+
end
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Formats
|
|
5
|
+
# RAR archive format support
|
|
6
|
+
#
|
|
7
|
+
# - Formats::Rar::Reader — the primary parser, verified against
|
|
8
|
+
# real WinRAR archives: listing, directories, mtimes, and
|
|
9
|
+
# extraction (native STORE decode with stored-CRC verification;
|
|
10
|
+
# foreign compressed streams fall back to the unrar command
|
|
11
|
+
# after the CRC check rejects them)
|
|
12
|
+
# - Formats::Rar::Writer (RAR4) and Formats::Rar::Rar5::Writer —
|
|
13
|
+
# STORE output is unrar-verified; compressed methods produce
|
|
14
|
+
# Omnizip-internal streams (see the README interop table)
|
|
15
|
+
# - Formats::Rar3 / Formats::Rar5 — legacy interfaces, thin
|
|
16
|
+
# adapters over the primary reader and the RAR5 writer
|
|
17
|
+
# - Multi-volume archives, encryption (RAR5), recovery records
|
|
18
|
+
module Rar
|
|
19
|
+
# Nested classes - autoloaded
|
|
20
|
+
autoload :Constants, "omnizip/formats/rar/constants"
|
|
21
|
+
autoload :Header, "omnizip/formats/rar/header"
|
|
22
|
+
autoload :BlockParser, "omnizip/formats/rar/block_parser"
|
|
23
|
+
autoload :Decompressor, "omnizip/formats/rar/decompressor"
|
|
24
|
+
autoload :VolumeManager, "omnizip/formats/rar/volume_manager"
|
|
25
|
+
autoload :RecoveryRecord, "omnizip/formats/rar/recovery_record"
|
|
26
|
+
autoload :ParityHandler, "omnizip/formats/rar/parity_handler"
|
|
27
|
+
autoload :ArchiveVerifier, "omnizip/formats/rar/archive_verifier"
|
|
28
|
+
autoload :ArchiveRepairer, "omnizip/formats/rar/archive_repairer"
|
|
29
|
+
autoload :Reader, "omnizip/formats/rar/reader"
|
|
30
|
+
autoload :Writer, "omnizip/formats/rar/writer"
|
|
31
|
+
autoload :RarFormatBase, "omnizip/formats/rar/rar_format_base"
|
|
32
|
+
autoload :ExternalWriter, "omnizip/formats/rar/external_writer"
|
|
33
|
+
autoload :LicenseValidator, "omnizip/formats/rar/license_validator"
|
|
34
|
+
# Models
|
|
35
|
+
autoload :Models, "omnizip/formats/rar/models"
|
|
36
|
+
# RAR5 support
|
|
37
|
+
module Rar5
|
|
38
|
+
autoload :VINT, "omnizip/formats/rar/rar5/vint"
|
|
39
|
+
autoload :CRC32, "omnizip/formats/rar/rar5/crc32"
|
|
40
|
+
autoload :Header, "omnizip/formats/rar/rar5/header"
|
|
41
|
+
# MainHeader/FileHeader live in header.rb directly under Rar5;
|
|
42
|
+
# without their own autoload entries, referencing them only
|
|
43
|
+
# works if something else loaded the file first.
|
|
44
|
+
autoload :MainHeader, "omnizip/formats/rar/rar5/header"
|
|
45
|
+
autoload :FileHeader, "omnizip/formats/rar/rar5/header"
|
|
46
|
+
autoload :Writer, "omnizip/formats/rar/rar5/writer"
|
|
47
|
+
# RAR5 compression
|
|
48
|
+
module Compression
|
|
49
|
+
autoload :Store, "omnizip/formats/rar/rar5/compression/store"
|
|
50
|
+
autoload :Lzma, "omnizip/formats/rar/rar5/compression/lzma"
|
|
51
|
+
autoload :Lzss, "omnizip/formats/rar/rar5/compression/lzss"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# RAR5 multi-volume
|
|
55
|
+
module MultiVolume
|
|
56
|
+
autoload :VolumeManager,
|
|
57
|
+
"omnizip/formats/rar/rar5/multi_volume/volume_manager"
|
|
58
|
+
autoload :VolumeWriter,
|
|
59
|
+
"omnizip/formats/rar/rar5/multi_volume/volume_writer"
|
|
60
|
+
autoload :VolumeSplitter,
|
|
61
|
+
"omnizip/formats/rar/rar5/multi_volume/volume_splitter"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# RAR5 models
|
|
65
|
+
module Models
|
|
66
|
+
autoload :VolumeOptions,
|
|
67
|
+
"omnizip/formats/rar/rar5/models/volume_options"
|
|
68
|
+
autoload :SolidOptions,
|
|
69
|
+
"omnizip/formats/rar/rar5/models/solid_options"
|
|
70
|
+
autoload :EncryptionOptions,
|
|
71
|
+
"omnizip/formats/rar/rar5/models/encryption_options"
|
|
72
|
+
autoload :RecoveryOptions,
|
|
73
|
+
"omnizip/formats/rar/rar5/models/recovery_options"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# RAR5 solid compression
|
|
77
|
+
module Solid
|
|
78
|
+
autoload :SolidManager, "omnizip/formats/rar/rar5/solid/solid_manager"
|
|
79
|
+
autoload :SolidEncoder, "omnizip/formats/rar/rar5/solid/solid_encoder"
|
|
80
|
+
autoload :SolidStream, "omnizip/formats/rar/rar5/solid/solid_stream"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# RAR5 encryption
|
|
84
|
+
module Encryption
|
|
85
|
+
autoload :Aes256Cbc, "omnizip/formats/rar/rar5/encryption/aes256_cbc"
|
|
86
|
+
autoload :EncryptionHeader,
|
|
87
|
+
"omnizip/formats/rar/rar5/encryption/encryption_header"
|
|
88
|
+
autoload :KeyDerivation,
|
|
89
|
+
"omnizip/formats/rar/rar5/encryption/key_derivation"
|
|
90
|
+
autoload :EncryptionManager,
|
|
91
|
+
"omnizip/formats/rar/rar5/encryption/encryption_manager"
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# RAR5 compression
|
|
95
|
+
module Compression
|
|
96
|
+
autoload :Store, "omnizip/formats/rar/rar5/compression/store"
|
|
97
|
+
autoload :Lzma, "omnizip/formats/rar/rar5/compression/lzma"
|
|
98
|
+
autoload :Lzss, "omnizip/formats/rar/rar5/compression/lzss"
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Compression layer
|
|
103
|
+
module Compression
|
|
104
|
+
autoload :BitStream, "omnizip/formats/rar/compression/bit_stream"
|
|
105
|
+
autoload :Dispatcher, "omnizip/formats/rar/compression/dispatcher"
|
|
106
|
+
module PPMd
|
|
107
|
+
autoload :Context, "omnizip/formats/rar/compression/ppmd/context"
|
|
108
|
+
autoload :Decoder, "omnizip/formats/rar/compression/ppmd/decoder"
|
|
109
|
+
autoload :Encoder, "omnizip/formats/rar/compression/ppmd/encoder"
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
module LZ77Huffman
|
|
113
|
+
autoload :SlidingWindow,
|
|
114
|
+
"omnizip/formats/rar/compression/lz77_huffman/sliding_window"
|
|
115
|
+
autoload :HuffmanCoder,
|
|
116
|
+
"omnizip/formats/rar/compression/lz77_huffman/huffman_coder"
|
|
117
|
+
autoload :HuffmanBuilder,
|
|
118
|
+
"omnizip/formats/rar/compression/lz77_huffman/huffman_builder"
|
|
119
|
+
autoload :MatchFinder,
|
|
120
|
+
"omnizip/formats/rar/compression/lz77_huffman/match_finder"
|
|
121
|
+
autoload :Decoder,
|
|
122
|
+
"omnizip/formats/rar/compression/lz77_huffman/decoder"
|
|
123
|
+
autoload :Encoder,
|
|
124
|
+
"omnizip/formats/rar/compression/lz77_huffman/encoder"
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
class << self
|
|
129
|
+
# Create a RAR archive, yielding the writer for entries.
|
|
130
|
+
# RAR5 is the default; pass version: 4 for the RAR4 writer.
|
|
131
|
+
# RAR5-only options (solid, multi-volume, password, recovery)
|
|
132
|
+
# are ignored for RAR4 — its writer warns about the
|
|
133
|
+
# unimplemented ones and raises for passwords.
|
|
134
|
+
#
|
|
135
|
+
# @param path [String] Output archive path
|
|
136
|
+
# @param options [Hash] Writer options
|
|
137
|
+
# @return [String, Array<String>] Path(s) of the created
|
|
138
|
+
# archive (a volume set returns every volume)
|
|
139
|
+
def create(path, options = {})
|
|
140
|
+
version = options.fetch(:version, 5)
|
|
141
|
+
writer = if version == 4
|
|
142
|
+
Writer.new(path, options)
|
|
143
|
+
else
|
|
144
|
+
Rar5::Writer.new(path, rar5_options(options))
|
|
145
|
+
end
|
|
146
|
+
yield writer if block_given?
|
|
147
|
+
writer.write
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Check if RAR extraction is available
|
|
151
|
+
#
|
|
152
|
+
# @return [Boolean] true if unrar available
|
|
153
|
+
def available?
|
|
154
|
+
Decompressor.available?
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Get decompressor information
|
|
158
|
+
#
|
|
159
|
+
# @return [Hash] Decompressor type and version
|
|
160
|
+
def decompressor_info
|
|
161
|
+
Decompressor.info
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Verify archive integrity
|
|
165
|
+
#
|
|
166
|
+
# @param archive_path [String] Path to RAR archive
|
|
167
|
+
# @return [ArchiveVerifier::VerificationResult] Verification result
|
|
168
|
+
def verify(archive_path, use_recovery: true)
|
|
169
|
+
ArchiveVerifier.new(archive_path).verify(use_recovery: use_recovery)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Repair corrupted archive
|
|
173
|
+
#
|
|
174
|
+
# @param archive_path [String] Path to corrupted RAR archive
|
|
175
|
+
# @param output_path [String] Path for repaired archive
|
|
176
|
+
# @return [ArchiveRepairer::RepairResult] Repair result
|
|
177
|
+
def repair(archive_path, output_path, options = {})
|
|
178
|
+
ArchiveRepairer.new.repair(archive_path, output_path, options)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
private
|
|
182
|
+
|
|
183
|
+
# Writer keywords the RAR5 writer understands
|
|
184
|
+
def rar5_options(options)
|
|
185
|
+
options.slice(:compression, :level, :solid, :multi_volume,
|
|
186
|
+
:volume_size, :volume_naming, :password,
|
|
187
|
+
:kdf_iterations, :recovery, :recovery_percent,
|
|
188
|
+
:include_mtime, :include_crc32, :dict_size)
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "zlib"
|
|
4
|
+
|
|
5
|
+
module Omnizip
|
|
6
|
+
module Formats
|
|
7
|
+
module Rar3
|
|
8
|
+
# RAR v3 compressor
|
|
9
|
+
#
|
|
10
|
+
# Compresses data using RAR v3 compression algorithms.
|
|
11
|
+
# This implementation uses DEFLATE as a compatible fallback
|
|
12
|
+
# for demonstration purposes. Full RAR compression requires
|
|
13
|
+
# proprietary algorithms.
|
|
14
|
+
#
|
|
15
|
+
# @example Compressing data
|
|
16
|
+
# compressor = Rar3::Compressor.new
|
|
17
|
+
# compressed = compressor.compress("Hello, World!", method: :normal)
|
|
18
|
+
class Compressor < Rar::RarFormatBase
|
|
19
|
+
# Initialize a RAR v3 compressor
|
|
20
|
+
def initialize
|
|
21
|
+
super("rar3")
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Compress data using RAR v3 methods
|
|
25
|
+
#
|
|
26
|
+
# @param data [String] The data to compress
|
|
27
|
+
# @param method [Symbol] The compression method
|
|
28
|
+
# @param options [Hash] Compression options
|
|
29
|
+
# @return [String] The compressed data
|
|
30
|
+
def compress(data, method: :normal, **_options)
|
|
31
|
+
case method
|
|
32
|
+
when :store
|
|
33
|
+
compress_store(data)
|
|
34
|
+
when :fastest
|
|
35
|
+
compress_deflate(data, level: Zlib::BEST_SPEED)
|
|
36
|
+
when :fast
|
|
37
|
+
compress_deflate(data, level: 3)
|
|
38
|
+
when :normal
|
|
39
|
+
compress_deflate(data, level: Zlib::DEFAULT_COMPRESSION)
|
|
40
|
+
when :good
|
|
41
|
+
compress_deflate(data, level: 7)
|
|
42
|
+
when :best
|
|
43
|
+
compress_deflate(data, level: Zlib::BEST_COMPRESSION)
|
|
44
|
+
else
|
|
45
|
+
raise FormatError,
|
|
46
|
+
"Unsupported compression method: #{method}"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
# Store data without compression
|
|
53
|
+
#
|
|
54
|
+
# @param data [String] The data to store
|
|
55
|
+
# @return [String] The uncompressed data
|
|
56
|
+
def compress_store(data)
|
|
57
|
+
data
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Compress using DEFLATE (compatible fallback)
|
|
61
|
+
#
|
|
62
|
+
# @param data [String] The data to compress
|
|
63
|
+
# @param level [Integer] The compression level
|
|
64
|
+
# @return [String] The compressed data
|
|
65
|
+
def compress_deflate(data, level:)
|
|
66
|
+
Zlib::Deflate.deflate(data, level)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|