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,218 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Copyright (C) 2024 Ribose Inc.
|
|
5
|
+
#
|
|
6
|
+
# This file is part of Omnizip.
|
|
7
|
+
#
|
|
8
|
+
# Omnizip is a pure Ruby port of 7-Zip compression algorithms.
|
|
9
|
+
# Based on the 7-Zip LZMA SDK by Igor Pavlov.
|
|
10
|
+
#
|
|
11
|
+
# This library is free software; you can redistribute it and/or
|
|
12
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
13
|
+
# License as published by the Free Software Foundation; either
|
|
14
|
+
# version 2.1 of the License, or (at your option) any later version.
|
|
15
|
+
#
|
|
16
|
+
# See the COPYING file for the complete text of the license.
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
require_relative "../cli/output_formatter"
|
|
20
|
+
require_relative "../formats/seven_zip/reader"
|
|
21
|
+
require_relative "../extraction"
|
|
22
|
+
|
|
23
|
+
module Omnizip
|
|
24
|
+
module Commands
|
|
25
|
+
# Command to list contents of .7z archives.
|
|
26
|
+
class ArchiveListCommand
|
|
27
|
+
attr_reader :options
|
|
28
|
+
|
|
29
|
+
# Initialize archive list command with options.
|
|
30
|
+
#
|
|
31
|
+
# @param options [Hash] Command options from Thor
|
|
32
|
+
def initialize(options = {})
|
|
33
|
+
@options = options
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Execute the archive list command.
|
|
37
|
+
#
|
|
38
|
+
# @param archive_file [String] Path to .7z archive
|
|
39
|
+
# @return [void]
|
|
40
|
+
def run(archive_file)
|
|
41
|
+
validate_input(archive_file)
|
|
42
|
+
|
|
43
|
+
verbose = options[:verbose] || false
|
|
44
|
+
patterns = Array(options[:pattern]) if options[:pattern]
|
|
45
|
+
excludes = Array(options[:exclude]) if options[:exclude]
|
|
46
|
+
count_only = options[:count] || false
|
|
47
|
+
|
|
48
|
+
list_archive(archive_file, verbose, patterns, excludes, count_only)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
def validate_input(archive_file)
|
|
54
|
+
unless File.exist?(archive_file)
|
|
55
|
+
raise Omnizip::IOError, "Archive not found: #{archive_file}"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
return if File.readable?(archive_file)
|
|
59
|
+
|
|
60
|
+
raise Omnizip::IOError,
|
|
61
|
+
"Archive not readable: #{archive_file}"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def list_archive(archive_file, verbose, patterns, excludes, count_only)
|
|
65
|
+
archive = if archive_file.end_with?(".zip")
|
|
66
|
+
Omnizip::Zip::File.open(archive_file)
|
|
67
|
+
elsif archive_file.end_with?(".rar")
|
|
68
|
+
Formats::Rar::Reader.new(archive_file).open
|
|
69
|
+
else
|
|
70
|
+
Formats::SevenZip::Reader.new(archive_file).open
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
entries = if patterns || excludes
|
|
74
|
+
filter_entries(archive, patterns, excludes)
|
|
75
|
+
else
|
|
76
|
+
archive.respond_to?(:entries) ? archive.entries : archive.to_a
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
if count_only
|
|
80
|
+
puts "Matches: #{entries.size}"
|
|
81
|
+
return
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
puts "Archive: #{archive_file}"
|
|
85
|
+
puts ""
|
|
86
|
+
|
|
87
|
+
if verbose
|
|
88
|
+
display_detailed_listing_filtered(entries)
|
|
89
|
+
else
|
|
90
|
+
display_simple_listing_filtered(entries)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
puts ""
|
|
94
|
+
summary_stats_filtered(entries)
|
|
95
|
+
rescue StandardError => e
|
|
96
|
+
raise Omnizip::CompressionError,
|
|
97
|
+
"Failed to list archive: #{e.message}"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def filter_entries(archive, patterns, excludes)
|
|
101
|
+
filter = Extraction::FilterChain.new
|
|
102
|
+
|
|
103
|
+
# Add include patterns
|
|
104
|
+
patterns&.each { |pattern| filter.include_pattern(pattern) }
|
|
105
|
+
|
|
106
|
+
# Add exclude patterns
|
|
107
|
+
excludes&.each { |pattern| filter.exclude_pattern(pattern) }
|
|
108
|
+
|
|
109
|
+
entries = archive.respond_to?(:entries) ? archive.entries : archive.to_a
|
|
110
|
+
filter.filter(entries)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def display_simple_listing_filtered(entries)
|
|
114
|
+
puts "Contents:"
|
|
115
|
+
puts ""
|
|
116
|
+
|
|
117
|
+
entries.each do |entry|
|
|
118
|
+
type_indicator = entry_directory?(entry) ? "D" : "F"
|
|
119
|
+
name = entry_name(entry)
|
|
120
|
+
puts " [#{type_indicator}] #{name}"
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def display_detailed_listing_filtered(entries)
|
|
125
|
+
puts "Type Size Compressed Modified Name"
|
|
126
|
+
puts "-" * 80
|
|
127
|
+
|
|
128
|
+
entries.each do |entry|
|
|
129
|
+
type = entry_directory?(entry) ? "Dir" : "File"
|
|
130
|
+
size = entry_directory?(entry) ? "-" : format_bytes(entry_size(entry))
|
|
131
|
+
compressed = if entry_directory?(entry) || !entry_has_stream?(entry)
|
|
132
|
+
"-"
|
|
133
|
+
else
|
|
134
|
+
format_bytes(entry_compressed_size(entry) || 0)
|
|
135
|
+
end
|
|
136
|
+
mtime = if entry_mtime(entry)
|
|
137
|
+
entry_mtime(entry).strftime("%Y-%m-%d %H:%M:%S")
|
|
138
|
+
else
|
|
139
|
+
"-"
|
|
140
|
+
end
|
|
141
|
+
name = entry_name(entry)
|
|
142
|
+
|
|
143
|
+
puts format(
|
|
144
|
+
"%-10s %-12s %-12s %-20s %s",
|
|
145
|
+
type,
|
|
146
|
+
size,
|
|
147
|
+
compressed,
|
|
148
|
+
mtime,
|
|
149
|
+
name,
|
|
150
|
+
)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def summary_stats_filtered(entries)
|
|
155
|
+
total_files = entries.count { |e| !entry_directory?(e) }
|
|
156
|
+
total_dirs = entries.count { |e| entry_directory?(e) }
|
|
157
|
+
total_size = entries.sum { |e| entry_size(e) || 0 }
|
|
158
|
+
total_compressed = entries.sum { |e| entry_compressed_size(e) || 0 }
|
|
159
|
+
|
|
160
|
+
puts "Summary:"
|
|
161
|
+
puts " Files: #{total_files}"
|
|
162
|
+
puts " Directories: #{total_dirs}"
|
|
163
|
+
puts " Total size: #{format_bytes(total_size)}"
|
|
164
|
+
return unless total_compressed.positive? && total_size.positive?
|
|
165
|
+
|
|
166
|
+
ratio = (1.0 - (total_compressed.to_f / total_size)) * 100
|
|
167
|
+
puts " Compressed size: #{format_bytes(total_compressed)}"
|
|
168
|
+
puts " Compression ratio: #{ratio.round(1)}%"
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def format_bytes(bytes)
|
|
172
|
+
return "0 B" if bytes.zero?
|
|
173
|
+
|
|
174
|
+
units = %w[B KB MB GB]
|
|
175
|
+
size = bytes.to_f
|
|
176
|
+
unit_idx = 0
|
|
177
|
+
|
|
178
|
+
while size >= 1024 && unit_idx < units.length - 1
|
|
179
|
+
size /= 1024.0
|
|
180
|
+
unit_idx += 1
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
if size < 10
|
|
184
|
+
format("%.2f %s", size, units[unit_idx])
|
|
185
|
+
elsif size < 100
|
|
186
|
+
format("%.1f %s", size, units[unit_idx])
|
|
187
|
+
else
|
|
188
|
+
format("%.0f %s", size, units[unit_idx])
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Helper methods to handle different entry types
|
|
193
|
+
def entry_name(entry)
|
|
194
|
+
entry.respond_to?(:name) ? entry.name : entry.to_s
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def entry_directory?(entry)
|
|
198
|
+
entry.respond_to?(:directory?) && entry.directory?
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def entry_size(entry)
|
|
202
|
+
entry.respond_to?(:size) ? entry.size : 0
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def entry_compressed_size(entry)
|
|
206
|
+
entry.respond_to?(:compressed_size) ? entry.compressed_size : nil
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def entry_has_stream?(entry)
|
|
210
|
+
entry.respond_to?(:has_stream?) ? entry.has_stream? : true
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def entry_mtime(entry)
|
|
214
|
+
entry.respond_to?(:mtime) ? entry.mtime : nil
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Commands
|
|
5
|
+
# Archive repair command
|
|
6
|
+
class ArchiveRepairCommand
|
|
7
|
+
attr_reader :options
|
|
8
|
+
|
|
9
|
+
# Initialize command
|
|
10
|
+
#
|
|
11
|
+
# @param options [Hash] Command options
|
|
12
|
+
def initialize(options = {})
|
|
13
|
+
@options = options
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Run repair
|
|
17
|
+
#
|
|
18
|
+
# @param input_path [String] Path to corrupted archive
|
|
19
|
+
# @param output_path [String] Path for repaired archive
|
|
20
|
+
def run(input_path, output_path)
|
|
21
|
+
require_relative "../formats/rar"
|
|
22
|
+
|
|
23
|
+
raise "Archive not found: #{input_path}" unless File.exist?(input_path)
|
|
24
|
+
|
|
25
|
+
# Detect format
|
|
26
|
+
format = detect_format(input_path)
|
|
27
|
+
|
|
28
|
+
case format
|
|
29
|
+
when :rar
|
|
30
|
+
repair_rar(input_path, output_path)
|
|
31
|
+
else
|
|
32
|
+
puts "Repair not supported for #{format} archives"
|
|
33
|
+
exit 1
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
# Detect archive format
|
|
40
|
+
#
|
|
41
|
+
# @param path [String] Archive path
|
|
42
|
+
# @return [Symbol] Format
|
|
43
|
+
def detect_format(path)
|
|
44
|
+
ext = File.extname(path).downcase
|
|
45
|
+
case ext
|
|
46
|
+
when ".rar", ".r00", ".r01"
|
|
47
|
+
:rar
|
|
48
|
+
when ".zip"
|
|
49
|
+
:zip
|
|
50
|
+
when ".7z"
|
|
51
|
+
:seven_zip
|
|
52
|
+
else
|
|
53
|
+
:unknown
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Repair RAR archive
|
|
58
|
+
#
|
|
59
|
+
# @param input_path [String] Path to corrupted archive
|
|
60
|
+
# @param output_path [String] Path for repaired archive
|
|
61
|
+
def repair_rar(input_path, output_path)
|
|
62
|
+
puts "Repairing #{input_path}..." if @options[:verbose]
|
|
63
|
+
|
|
64
|
+
repair_options = {
|
|
65
|
+
use_external_rev: !@options[:no_external_rev],
|
|
66
|
+
verify_repaired: !@options[:no_verify],
|
|
67
|
+
verbose: @options[:verbose],
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
result = Omnizip::Formats::Rar.repair(
|
|
71
|
+
input_path,
|
|
72
|
+
output_path,
|
|
73
|
+
repair_options,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
display_repair_result(input_path, output_path, result)
|
|
77
|
+
|
|
78
|
+
exit 1 unless result.success?
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Display repair results
|
|
82
|
+
#
|
|
83
|
+
# @param input_path [String] Input archive path
|
|
84
|
+
# @param output_path [String] Output archive path
|
|
85
|
+
# @param result [ArchiveRepairer::RepairResult] Repair results
|
|
86
|
+
def display_repair_result(input_path, output_path, result)
|
|
87
|
+
puts "\nRepair Results:"
|
|
88
|
+
puts "Input: #{input_path}"
|
|
89
|
+
puts "Output: #{output_path}"
|
|
90
|
+
|
|
91
|
+
if result.success?
|
|
92
|
+
puts "\nStatus: SUCCESS"
|
|
93
|
+
puts "Repaired files: #{result.repaired_files.size}"
|
|
94
|
+
puts "Repaired blocks: #{result.repaired_blocks.size}"
|
|
95
|
+
|
|
96
|
+
if @options[:verbose] && result.repaired_files.any?
|
|
97
|
+
puts "\nRepaired:"
|
|
98
|
+
result.repaired_files.each do |filename|
|
|
99
|
+
puts " ✓ #{filename}"
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
else
|
|
103
|
+
puts "\nStatus: FAILED"
|
|
104
|
+
|
|
105
|
+
if result.repaired_files.any?
|
|
106
|
+
puts "Partially repaired: #{result.repaired_files.size} files"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
if result.unrepaired_files.any?
|
|
110
|
+
puts "Unrepaired: #{result.unrepaired_files.size} files"
|
|
111
|
+
|
|
112
|
+
if @options[:verbose]
|
|
113
|
+
result.unrepaired_files.each do |filename|
|
|
114
|
+
puts " ✗ #{filename}"
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
if result.errors.any?
|
|
120
|
+
puts "\nErrors:"
|
|
121
|
+
result.errors.each do |error|
|
|
122
|
+
puts " - #{error}"
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
puts "\n#{result.summary}"
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Commands
|
|
5
|
+
# Archive verification command
|
|
6
|
+
class ArchiveVerifyCommand
|
|
7
|
+
attr_reader :options
|
|
8
|
+
|
|
9
|
+
# Initialize command
|
|
10
|
+
#
|
|
11
|
+
# @param options [Hash] Command options
|
|
12
|
+
def initialize(options = {})
|
|
13
|
+
@options = options
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Run verification
|
|
17
|
+
#
|
|
18
|
+
# @param archive_path [String] Path to archive
|
|
19
|
+
def run(archive_path)
|
|
20
|
+
require_relative "../formats/rar"
|
|
21
|
+
|
|
22
|
+
unless File.exist?(archive_path)
|
|
23
|
+
raise "Archive not found: #{archive_path}"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Detect format
|
|
27
|
+
format = detect_format(archive_path)
|
|
28
|
+
|
|
29
|
+
case format
|
|
30
|
+
when :rar
|
|
31
|
+
verify_rar(archive_path)
|
|
32
|
+
else
|
|
33
|
+
puts "Verification not supported for #{format} archives"
|
|
34
|
+
exit 1
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
# Detect archive format
|
|
41
|
+
#
|
|
42
|
+
# @param path [String] Archive path
|
|
43
|
+
# @return [Symbol] Format (:rar, :zip, :7z)
|
|
44
|
+
def detect_format(path)
|
|
45
|
+
ext = File.extname(path).downcase
|
|
46
|
+
case ext
|
|
47
|
+
when ".rar", ".r00", ".r01"
|
|
48
|
+
:rar
|
|
49
|
+
when ".zip"
|
|
50
|
+
:zip
|
|
51
|
+
when ".7z"
|
|
52
|
+
:seven_zip
|
|
53
|
+
else
|
|
54
|
+
:unknown
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Verify RAR archive
|
|
59
|
+
#
|
|
60
|
+
# @param archive_path [String] Path to RAR archive
|
|
61
|
+
def verify_rar(archive_path)
|
|
62
|
+
puts "Verifying #{archive_path}..." if @options[:verbose]
|
|
63
|
+
|
|
64
|
+
result = Omnizip::Formats::Rar.verify(
|
|
65
|
+
archive_path,
|
|
66
|
+
use_recovery: !@options[:no_recovery],
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
display_verification_result(archive_path, result)
|
|
70
|
+
|
|
71
|
+
exit 1 unless result.valid?
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Display verification results
|
|
75
|
+
#
|
|
76
|
+
# @param archive_path [String] Archive path
|
|
77
|
+
# @param result [ArchiveVerifier::VerificationResult] Results
|
|
78
|
+
def display_verification_result(archive_path, result)
|
|
79
|
+
puts "\nArchive: #{archive_path}"
|
|
80
|
+
puts "Format: RAR"
|
|
81
|
+
|
|
82
|
+
if result.recovery_available
|
|
83
|
+
puts "Recovery records: Yes"
|
|
84
|
+
else
|
|
85
|
+
puts "Recovery records: No"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
puts "\nFiles:"
|
|
89
|
+
puts " Total: #{result.files_total}"
|
|
90
|
+
puts " OK: #{result.files_ok}"
|
|
91
|
+
puts " Corrupted: #{result.files_corrupted}"
|
|
92
|
+
|
|
93
|
+
if result.files_corrupted.positive?
|
|
94
|
+
puts "\nCorrupted files:"
|
|
95
|
+
result.corrupted_files.each do |filename|
|
|
96
|
+
puts " - #{filename}"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
if result.can_repair?
|
|
100
|
+
puts "\nCan repair: Yes (using recovery records)"
|
|
101
|
+
else
|
|
102
|
+
puts "\nCan repair: No"
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
if @options[:verbose] && result.errors.any?
|
|
107
|
+
puts "\nErrors:"
|
|
108
|
+
result.errors.each do |error|
|
|
109
|
+
puts " - #{error}"
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
puts "\n#{result.summary}"
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Copyright (C) 2024 Ribose Inc.
|
|
5
|
+
#
|
|
6
|
+
# This file is part of Omnizip.
|
|
7
|
+
#
|
|
8
|
+
# Omnizip is a pure Ruby port of 7-Zip compression algorithms.
|
|
9
|
+
# Based on the 7-Zip LZMA SDK by Igor Pavlov.
|
|
10
|
+
#
|
|
11
|
+
# This library is free software; you can redistribute it and/or
|
|
12
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
13
|
+
# License as published by the Free Software Foundation; either
|
|
14
|
+
# version 2.1 of the License, or (at your option) any later version.
|
|
15
|
+
#
|
|
16
|
+
# See the COPYING file for the complete text of the license.
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
require_relative "../cli/output_formatter"
|
|
20
|
+
|
|
21
|
+
module Omnizip
|
|
22
|
+
module Commands
|
|
23
|
+
# Command to compress files using specified algorithm.
|
|
24
|
+
class CompressCommand
|
|
25
|
+
attr_reader :options
|
|
26
|
+
|
|
27
|
+
# Initialize compress command with options.
|
|
28
|
+
#
|
|
29
|
+
# @param options [Hash] Command options from Thor
|
|
30
|
+
def initialize(options = {})
|
|
31
|
+
@options = options
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Execute the compress command.
|
|
35
|
+
#
|
|
36
|
+
# @param input_file [String] Path to input file
|
|
37
|
+
# @param output_file [String] Path to output file
|
|
38
|
+
# @return [void]
|
|
39
|
+
def run(input_file, output_file)
|
|
40
|
+
validate_inputs(input_file, output_file)
|
|
41
|
+
|
|
42
|
+
algorithm_name = options[:algorithm] || "lzma"
|
|
43
|
+
level = options[:level] || 5
|
|
44
|
+
verbose = options[:verbose] || false
|
|
45
|
+
|
|
46
|
+
CliOutputFormatter.verbose_puts(
|
|
47
|
+
"Compressing #{input_file} to #{output_file}...",
|
|
48
|
+
verbose,
|
|
49
|
+
)
|
|
50
|
+
CliOutputFormatter.verbose_puts(
|
|
51
|
+
"Algorithm: #{algorithm_name}, Level: #{level}",
|
|
52
|
+
verbose,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
start_time = Time.now
|
|
56
|
+
|
|
57
|
+
compress_file(input_file, output_file, algorithm_name, level)
|
|
58
|
+
|
|
59
|
+
elapsed = Time.now - start_time
|
|
60
|
+
|
|
61
|
+
input_size = File.size(input_file)
|
|
62
|
+
output_size = File.size(output_file)
|
|
63
|
+
|
|
64
|
+
if verbose
|
|
65
|
+
puts ""
|
|
66
|
+
puts CliOutputFormatter.format_compression_stats(
|
|
67
|
+
input_size,
|
|
68
|
+
output_size,
|
|
69
|
+
elapsed,
|
|
70
|
+
)
|
|
71
|
+
else
|
|
72
|
+
puts "Compressed: #{input_file} -> #{output_file}"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
def validate_inputs(input_file, output_file)
|
|
79
|
+
unless File.exist?(input_file)
|
|
80
|
+
raise Omnizip::IOError, "Input file not found: #{input_file}"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
unless File.readable?(input_file)
|
|
84
|
+
raise Omnizip::IOError,
|
|
85
|
+
"Input file not readable: #{input_file}"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
output_dir = File.dirname(output_file)
|
|
89
|
+
unless File.directory?(output_dir)
|
|
90
|
+
raise Omnizip::IOError,
|
|
91
|
+
"Output directory does not exist: #{output_dir}"
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
return if File.writable?(output_dir)
|
|
95
|
+
|
|
96
|
+
raise Omnizip::IOError,
|
|
97
|
+
"Output directory not writable: #{output_dir}"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def compress_file(input_file, output_file, algorithm_name, level)
|
|
101
|
+
algorithm_class = AlgorithmRegistry.get(algorithm_name.to_sym)
|
|
102
|
+
algorithm = algorithm_class.new(level: level)
|
|
103
|
+
|
|
104
|
+
File.open(input_file, "rb") do |input|
|
|
105
|
+
File.open(output_file, "wb") do |output|
|
|
106
|
+
algorithm.compress(input, output)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
rescue UnknownAlgorithmError => e
|
|
110
|
+
raise e
|
|
111
|
+
rescue StandardError => e
|
|
112
|
+
raise Omnizip::CompressionError,
|
|
113
|
+
"Failed to compress file: #{e.message}"
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Copyright (C) 2024 Ribose Inc.
|
|
5
|
+
#
|
|
6
|
+
# This file is part of Omnizip.
|
|
7
|
+
#
|
|
8
|
+
# Omnizip is a pure Ruby port of 7-Zip compression algorithms.
|
|
9
|
+
# Based on the 7-Zip LZMA SDK by Igor Pavlov.
|
|
10
|
+
#
|
|
11
|
+
# This library is free software; you can redistribute it and/or
|
|
12
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
13
|
+
# License as published by the Free Software Foundation; either
|
|
14
|
+
# version 2.1 of the License, or (at your option) any later version.
|
|
15
|
+
#
|
|
16
|
+
# See the COPYING file for the complete text of the license.
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
require_relative "../cli/output_formatter"
|
|
20
|
+
|
|
21
|
+
module Omnizip
|
|
22
|
+
module Commands
|
|
23
|
+
# Command to decompress files using specified algorithm.
|
|
24
|
+
class DecompressCommand
|
|
25
|
+
attr_reader :options
|
|
26
|
+
|
|
27
|
+
# Initialize decompress command with options.
|
|
28
|
+
#
|
|
29
|
+
# @param options [Hash] Command options from Thor
|
|
30
|
+
def initialize(options = {})
|
|
31
|
+
@options = options
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Execute the decompress command.
|
|
35
|
+
#
|
|
36
|
+
# @param input_file [String] Path to input file
|
|
37
|
+
# @param output_file [String] Path to output file
|
|
38
|
+
# @return [void]
|
|
39
|
+
def run(input_file, output_file)
|
|
40
|
+
validate_inputs(input_file, output_file)
|
|
41
|
+
|
|
42
|
+
algorithm_name = options[:algorithm] || detect_algorithm
|
|
43
|
+
verbose = options[:verbose] || false
|
|
44
|
+
|
|
45
|
+
CliOutputFormatter.verbose_puts(
|
|
46
|
+
"Decompressing #{input_file} to #{output_file}...",
|
|
47
|
+
verbose,
|
|
48
|
+
)
|
|
49
|
+
CliOutputFormatter.verbose_puts(
|
|
50
|
+
"Algorithm: #{algorithm_name}",
|
|
51
|
+
verbose,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
start_time = Time.now
|
|
55
|
+
|
|
56
|
+
decompress_file(input_file, output_file, algorithm_name)
|
|
57
|
+
|
|
58
|
+
elapsed = Time.now - start_time
|
|
59
|
+
|
|
60
|
+
input_size = File.size(input_file)
|
|
61
|
+
output_size = File.size(output_file)
|
|
62
|
+
|
|
63
|
+
if verbose
|
|
64
|
+
puts ""
|
|
65
|
+
puts CliOutputFormatter.format_compression_stats(
|
|
66
|
+
output_size,
|
|
67
|
+
input_size,
|
|
68
|
+
elapsed,
|
|
69
|
+
)
|
|
70
|
+
else
|
|
71
|
+
puts "Decompressed: #{input_file} -> #{output_file}"
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
def validate_inputs(input_file, output_file)
|
|
78
|
+
unless File.exist?(input_file)
|
|
79
|
+
raise Omnizip::IOError, "Input file not found: #{input_file}"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
unless File.readable?(input_file)
|
|
83
|
+
raise Omnizip::IOError,
|
|
84
|
+
"Input file not readable: #{input_file}"
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
output_dir = File.dirname(output_file)
|
|
88
|
+
unless File.directory?(output_dir)
|
|
89
|
+
raise Omnizip::IOError,
|
|
90
|
+
"Output directory does not exist: #{output_dir}"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
return if File.writable?(output_dir)
|
|
94
|
+
|
|
95
|
+
raise Omnizip::IOError,
|
|
96
|
+
"Output directory not writable: #{output_dir}"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def detect_algorithm
|
|
100
|
+
"lzma"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def decompress_file(input_file, output_file, algorithm_name)
|
|
104
|
+
algorithm_class = AlgorithmRegistry.get(algorithm_name.to_sym)
|
|
105
|
+
algorithm = algorithm_class.new
|
|
106
|
+
|
|
107
|
+
File.open(input_file, "rb") do |input|
|
|
108
|
+
File.open(output_file, "wb") do |output|
|
|
109
|
+
algorithm.decompress(input, output)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
rescue UnknownAlgorithmError => e
|
|
113
|
+
raise e
|
|
114
|
+
rescue StandardError => e
|
|
115
|
+
raise Omnizip::CompressionError,
|
|
116
|
+
"Failed to decompress file: #{e.message}"
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|