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.
Files changed (511) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +32 -0
  4. data/.rubocop_todo.yml +754 -0
  5. data/COPYING +502 -0
  6. data/Gemfile +17 -0
  7. data/LICENSE +12 -0
  8. data/README.adoc +1045 -0
  9. data/Rakefile +12 -0
  10. data/benchmark/README.md +260 -0
  11. data/benchmark/benchmark_suite.rb +125 -0
  12. data/benchmark/compression_bench.rb +181 -0
  13. data/benchmark/filter_bench.rb +180 -0
  14. data/benchmark/models/benchmark_result.rb +59 -0
  15. data/benchmark/models/comparison_result.rb +69 -0
  16. data/benchmark/profile_suite.rb +167 -0
  17. data/benchmark/reporter.rb +150 -0
  18. data/benchmark/run_benchmarks.rb +66 -0
  19. data/benchmark/test_data.rb +137 -0
  20. data/config/formats/rar3_spec.yml +91 -0
  21. data/config/formats/rar5_spec.yml +102 -0
  22. data/docs/.github/workflows/docs.yml +142 -0
  23. data/docs/.gitignore +21 -0
  24. data/docs/.lychee.toml +67 -0
  25. data/docs/Gemfile +13 -0
  26. data/docs/RAR_WRITE_SUPPORT.md +26 -0
  27. data/docs/README.md +101 -0
  28. data/docs/_config.yml +112 -0
  29. data/docs/assets/logo.svg +1 -0
  30. data/docs/assets/omnizip-logo.pdf +1540 -11
  31. data/docs/comparison/feature-matrix.adoc +694 -0
  32. data/docs/comparison/index.adoc +113 -0
  33. data/docs/comparison/vs-7zip.adoc +309 -0
  34. data/docs/comparison/vs-peazip.adoc +77 -0
  35. data/docs/comparison/vs-rubyzip.adoc +342 -0
  36. data/docs/comparison/vs-winrar.adoc +100 -0
  37. data/docs/compatibility.adoc +579 -0
  38. data/docs/concepts/index.adoc +129 -0
  39. data/docs/developer/architecture.adoc +256 -0
  40. data/docs/developer/contributing.adoc +158 -0
  41. data/docs/developer/index.adoc +25 -0
  42. data/docs/developer/testing.adoc +212 -0
  43. data/docs/getting-started/basic-usage.adoc +271 -0
  44. data/docs/getting-started/index.adoc +42 -0
  45. data/docs/getting-started/installation.adoc +138 -0
  46. data/docs/getting-started/quick-start.adoc +185 -0
  47. data/docs/getting-started/your-first-archive.adoc +218 -0
  48. data/docs/guides/advanced-features/encryption.adoc +300 -0
  49. data/docs/guides/advanced-features/index.adoc +49 -0
  50. data/docs/guides/advanced-features/parallel-processing.adoc +246 -0
  51. data/docs/guides/advanced-features/progress-tracking.adoc +320 -0
  52. data/docs/guides/advanced-features/streaming.adoc +212 -0
  53. data/docs/guides/archive-formats/gzip-format.adoc +107 -0
  54. data/docs/guides/archive-formats/index.adoc +130 -0
  55. data/docs/guides/archive-formats/rar-format.adoc +104 -0
  56. data/docs/guides/archive-formats/rar5.adoc +521 -0
  57. data/docs/guides/archive-formats/seven-zip-format.adoc +35 -0
  58. data/docs/guides/archive-formats/tar-format.adoc +106 -0
  59. data/docs/guides/archive-formats/xz-format.adoc +118 -0
  60. data/docs/guides/archive-formats/zip-format.adoc +35 -0
  61. data/docs/guides/compression-algorithms/bzip2.adoc +113 -0
  62. data/docs/guides/compression-algorithms/deflate.adoc +319 -0
  63. data/docs/guides/compression-algorithms/index.adoc +190 -0
  64. data/docs/guides/compression-algorithms/lzma.adoc +398 -0
  65. data/docs/guides/compression-algorithms/lzma2.adoc +327 -0
  66. data/docs/guides/compression-algorithms/ppmd.adoc +316 -0
  67. data/docs/guides/compression-algorithms/zstandard.adoc +361 -0
  68. data/docs/guides/creating-archives.adoc +354 -0
  69. data/docs/guides/extracting-archives.adoc +53 -0
  70. data/docs/guides/format-conversion.adoc +64 -0
  71. data/docs/guides/index.adoc +49 -0
  72. data/docs/guides/migration-rubyzip.adoc +217 -0
  73. data/docs/guides/parity-archives.adoc +605 -0
  74. data/docs/guides/performance-tuning.adoc +88 -0
  75. data/docs/index.adoc +218 -0
  76. data/docs/lychee.toml +67 -0
  77. data/docs/reference/api/overview.adoc +188 -0
  78. data/docs/reference/cli/compress-command.adoc +114 -0
  79. data/docs/reference/cli/overview.adoc +140 -0
  80. data/docs/reference/index.adoc +26 -0
  81. data/docs/resources/faq.adoc +185 -0
  82. data/docs/resources/quick-reference.adoc +222 -0
  83. data/docs/troubleshooting/index.adoc +208 -0
  84. data/examples/api_comparison.rb +205 -0
  85. data/examples/deflate64_example.rb +96 -0
  86. data/examples/par2_demo.rb +121 -0
  87. data/examples/quick_start_native.rb +150 -0
  88. data/examples/quick_start_rubyzip.rb +115 -0
  89. data/examples/rubyzip_compatibility_demo.rb +194 -0
  90. data/exe/omnizip +27 -0
  91. data/lib/omnizip/algorithm.rb +130 -0
  92. data/lib/omnizip/algorithm_registry.rb +86 -0
  93. data/lib/omnizip/algorithms/.keep +0 -0
  94. data/lib/omnizip/algorithms/bzip2/bwt.rb +225 -0
  95. data/lib/omnizip/algorithms/bzip2/decoder.rb +193 -0
  96. data/lib/omnizip/algorithms/bzip2/encoder.rb +237 -0
  97. data/lib/omnizip/algorithms/bzip2/huffman.rb +206 -0
  98. data/lib/omnizip/algorithms/bzip2/mtf.rb +101 -0
  99. data/lib/omnizip/algorithms/bzip2/rle.rb +151 -0
  100. data/lib/omnizip/algorithms/bzip2.rb +130 -0
  101. data/lib/omnizip/algorithms/deflate/constants.rb +28 -0
  102. data/lib/omnizip/algorithms/deflate/decoder.rb +38 -0
  103. data/lib/omnizip/algorithms/deflate/encoder.rb +46 -0
  104. data/lib/omnizip/algorithms/deflate.rb +128 -0
  105. data/lib/omnizip/algorithms/deflate64/constants.rb +45 -0
  106. data/lib/omnizip/algorithms/deflate64/decoder.rb +153 -0
  107. data/lib/omnizip/algorithms/deflate64/encoder.rb +98 -0
  108. data/lib/omnizip/algorithms/deflate64/huffman_coder.rb +354 -0
  109. data/lib/omnizip/algorithms/deflate64/lz77_encoder.rb +142 -0
  110. data/lib/omnizip/algorithms/deflate64.rb +109 -0
  111. data/lib/omnizip/algorithms/lzma/bit_model.rb +120 -0
  112. data/lib/omnizip/algorithms/lzma/constants.rb +112 -0
  113. data/lib/omnizip/algorithms/lzma/decoder.rb +148 -0
  114. data/lib/omnizip/algorithms/lzma/dictionary.rb +69 -0
  115. data/lib/omnizip/algorithms/lzma/distance_coder.rb +415 -0
  116. data/lib/omnizip/algorithms/lzma/encoder.rb +142 -0
  117. data/lib/omnizip/algorithms/lzma/length_coder.rb +260 -0
  118. data/lib/omnizip/algorithms/lzma/literal_decoder.rb +320 -0
  119. data/lib/omnizip/algorithms/lzma/literal_encoder.rb +210 -0
  120. data/lib/omnizip/algorithms/lzma/lzip_decoder.rb +341 -0
  121. data/lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb +192 -0
  122. data/lib/omnizip/algorithms/lzma/lzma_state.rb +128 -0
  123. data/lib/omnizip/algorithms/lzma/match.rb +32 -0
  124. data/lib/omnizip/algorithms/lzma/match_finder.rb +205 -0
  125. data/lib/omnizip/algorithms/lzma/match_finder_config.rb +142 -0
  126. data/lib/omnizip/algorithms/lzma/match_finder_factory.rb +88 -0
  127. data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +130 -0
  128. data/lib/omnizip/algorithms/lzma/probability_models.rb +72 -0
  129. data/lib/omnizip/algorithms/lzma/range_coder.rb +85 -0
  130. data/lib/omnizip/algorithms/lzma/range_decoder.rb +434 -0
  131. data/lib/omnizip/algorithms/lzma/range_encoder.rb +194 -0
  132. data/lib/omnizip/algorithms/lzma/state.rb +127 -0
  133. data/lib/omnizip/algorithms/lzma/xz_buffered_range_encoder.rb +325 -0
  134. data/lib/omnizip/algorithms/lzma/xz_encoder.rb +426 -0
  135. data/lib/omnizip/algorithms/lzma/xz_encoder_fast.rb +645 -0
  136. data/lib/omnizip/algorithms/lzma/xz_match_finder_adapter.rb +227 -0
  137. data/lib/omnizip/algorithms/lzma/xz_price_calculator.rb +169 -0
  138. data/lib/omnizip/algorithms/lzma/xz_probability_models.rb +261 -0
  139. data/lib/omnizip/algorithms/lzma/xz_range_encoder.rb +223 -0
  140. data/lib/omnizip/algorithms/lzma/xz_range_encoder_exact.rb +331 -0
  141. data/lib/omnizip/algorithms/lzma/xz_state.rb +116 -0
  142. data/lib/omnizip/algorithms/lzma/xz_utils_decoder.rb +2055 -0
  143. data/lib/omnizip/algorithms/lzma.rb +238 -0
  144. data/lib/omnizip/algorithms/lzma2/chunk_manager.rb +182 -0
  145. data/lib/omnizip/algorithms/lzma2/constants.rb +41 -0
  146. data/lib/omnizip/algorithms/lzma2/encoder.rb +147 -0
  147. data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +161 -0
  148. data/lib/omnizip/algorithms/lzma2/properties.rb +179 -0
  149. data/lib/omnizip/algorithms/lzma2/simple_lzma2_encoder.rb +127 -0
  150. data/lib/omnizip/algorithms/lzma2/xz_encoder_adapter.rb +85 -0
  151. data/lib/omnizip/algorithms/lzma2.rb +141 -0
  152. data/lib/omnizip/algorithms/ppmd7/constants.rb +74 -0
  153. data/lib/omnizip/algorithms/ppmd7/context.rb +154 -0
  154. data/lib/omnizip/algorithms/ppmd7/decoder.rb +126 -0
  155. data/lib/omnizip/algorithms/ppmd7/encoder.rb +163 -0
  156. data/lib/omnizip/algorithms/ppmd7/model.rb +248 -0
  157. data/lib/omnizip/algorithms/ppmd7/symbol_state.rb +57 -0
  158. data/lib/omnizip/algorithms/ppmd7.rb +116 -0
  159. data/lib/omnizip/algorithms/ppmd8/constants.rb +61 -0
  160. data/lib/omnizip/algorithms/ppmd8/context.rb +34 -0
  161. data/lib/omnizip/algorithms/ppmd8/decoder.rb +107 -0
  162. data/lib/omnizip/algorithms/ppmd8/encoder.rb +138 -0
  163. data/lib/omnizip/algorithms/ppmd8/model.rb +250 -0
  164. data/lib/omnizip/algorithms/ppmd8/restoration_method.rb +78 -0
  165. data/lib/omnizip/algorithms/ppmd8.rb +82 -0
  166. data/lib/omnizip/algorithms/ppmd_base.rb +138 -0
  167. data/lib/omnizip/algorithms/sevenzip_lzma2.rb +123 -0
  168. data/lib/omnizip/algorithms/xz_lzma2.rb +118 -0
  169. data/lib/omnizip/algorithms/zstandard/constants.rb +25 -0
  170. data/lib/omnizip/algorithms/zstandard/decoder.rb +46 -0
  171. data/lib/omnizip/algorithms/zstandard/encoder.rb +51 -0
  172. data/lib/omnizip/algorithms/zstandard.rb +138 -0
  173. data/lib/omnizip/buffer/memory_archive.rb +251 -0
  174. data/lib/omnizip/buffer/memory_extractor.rb +224 -0
  175. data/lib/omnizip/buffer.rb +176 -0
  176. data/lib/omnizip/checksum_registry.rb +114 -0
  177. data/lib/omnizip/checksums/crc32.rb +100 -0
  178. data/lib/omnizip/checksums/crc64.rb +101 -0
  179. data/lib/omnizip/checksums/crc_base.rb +158 -0
  180. data/lib/omnizip/checksums/verifier.rb +131 -0
  181. data/lib/omnizip/chunked/memory_manager.rb +194 -0
  182. data/lib/omnizip/chunked/reader.rb +78 -0
  183. data/lib/omnizip/chunked/writer.rb +120 -0
  184. data/lib/omnizip/chunked.rb +129 -0
  185. data/lib/omnizip/cli/output_formatter.rb +104 -0
  186. data/lib/omnizip/cli.rb +572 -0
  187. data/lib/omnizip/commands/.keep +0 -0
  188. data/lib/omnizip/commands/archive_create_command.rb +427 -0
  189. data/lib/omnizip/commands/archive_extract_command.rb +272 -0
  190. data/lib/omnizip/commands/archive_list_command.rb +218 -0
  191. data/lib/omnizip/commands/archive_repair_command.rb +131 -0
  192. data/lib/omnizip/commands/archive_verify_command.rb +117 -0
  193. data/lib/omnizip/commands/compress_command.rb +117 -0
  194. data/lib/omnizip/commands/decompress_command.rb +120 -0
  195. data/lib/omnizip/commands/list_command.rb +53 -0
  196. data/lib/omnizip/commands/metadata_command.rb +153 -0
  197. data/lib/omnizip/commands/parity_create_command.rb +122 -0
  198. data/lib/omnizip/commands/parity_repair_command.rb +122 -0
  199. data/lib/omnizip/commands/parity_verify_command.rb +124 -0
  200. data/lib/omnizip/commands/profile_list_command.rb +56 -0
  201. data/lib/omnizip/commands/profile_show_command.rb +44 -0
  202. data/lib/omnizip/convenience.rb +359 -0
  203. data/lib/omnizip/converter/conversion_registry.rb +49 -0
  204. data/lib/omnizip/converter/conversion_strategy.rb +121 -0
  205. data/lib/omnizip/converter/seven_zip_to_zip_strategy.rb +97 -0
  206. data/lib/omnizip/converter/zip_to_seven_zip_strategy.rb +112 -0
  207. data/lib/omnizip/converter.rb +105 -0
  208. data/lib/omnizip/crypto/aes256/cipher.rb +100 -0
  209. data/lib/omnizip/crypto/aes256/constants.rb +28 -0
  210. data/lib/omnizip/crypto/aes256/key_derivation.rb +101 -0
  211. data/lib/omnizip/crypto/aes256.rb +102 -0
  212. data/lib/omnizip/error.rb +106 -0
  213. data/lib/omnizip/eta/exponential_smoothing_estimator.rb +98 -0
  214. data/lib/omnizip/eta/moving_average_estimator.rb +99 -0
  215. data/lib/omnizip/eta/rate_calculator.rb +104 -0
  216. data/lib/omnizip/eta/sample_history.rb +143 -0
  217. data/lib/omnizip/eta/time_estimator.rb +106 -0
  218. data/lib/omnizip/eta.rb +63 -0
  219. data/lib/omnizip/extraction/filter_chain.rb +177 -0
  220. data/lib/omnizip/extraction/glob_pattern.rb +140 -0
  221. data/lib/omnizip/extraction/pattern_matcher.rb +70 -0
  222. data/lib/omnizip/extraction/predicate_pattern.rb +52 -0
  223. data/lib/omnizip/extraction/regex_pattern.rb +50 -0
  224. data/lib/omnizip/extraction/selective_extractor.rb +240 -0
  225. data/lib/omnizip/extraction.rb +111 -0
  226. data/lib/omnizip/file_type/mime_classifier.rb +144 -0
  227. data/lib/omnizip/file_type.rb +113 -0
  228. data/lib/omnizip/filter.rb +139 -0
  229. data/lib/omnizip/filter_pipeline.rb +108 -0
  230. data/lib/omnizip/filter_registry.rb +166 -0
  231. data/lib/omnizip/filters/bcj.rb +279 -0
  232. data/lib/omnizip/filters/bcj2/constants.rb +53 -0
  233. data/lib/omnizip/filters/bcj2/decoder.rb +200 -0
  234. data/lib/omnizip/filters/bcj2/encoder.rb +61 -0
  235. data/lib/omnizip/filters/bcj2/stream_data.rb +93 -0
  236. data/lib/omnizip/filters/bcj2.rb +99 -0
  237. data/lib/omnizip/filters/bcj_arm.rb +176 -0
  238. data/lib/omnizip/filters/bcj_arm64.rb +244 -0
  239. data/lib/omnizip/filters/bcj_ia64.rb +196 -0
  240. data/lib/omnizip/filters/bcj_ppc.rb +190 -0
  241. data/lib/omnizip/filters/bcj_sparc.rb +176 -0
  242. data/lib/omnizip/filters/bcj_x86.rb +193 -0
  243. data/lib/omnizip/filters/delta.rb +196 -0
  244. data/lib/omnizip/filters/filter_base.rb +72 -0
  245. data/lib/omnizip/filters/registry.rb +123 -0
  246. data/lib/omnizip/filters/xz_delta.rb +258 -0
  247. data/lib/omnizip/format_detector.rb +162 -0
  248. data/lib/omnizip/format_registry.rb +59 -0
  249. data/lib/omnizip/formats/.keep +0 -0
  250. data/lib/omnizip/formats/bzip2_file.rb +172 -0
  251. data/lib/omnizip/formats/cpio/constants.rb +55 -0
  252. data/lib/omnizip/formats/cpio/entry.rb +385 -0
  253. data/lib/omnizip/formats/cpio/reader.rb +196 -0
  254. data/lib/omnizip/formats/cpio/writer.rb +234 -0
  255. data/lib/omnizip/formats/cpio.rb +140 -0
  256. data/lib/omnizip/formats/format_spec_loader.rb +230 -0
  257. data/lib/omnizip/formats/gzip.rb +238 -0
  258. data/lib/omnizip/formats/iso/directory_builder.rb +297 -0
  259. data/lib/omnizip/formats/iso/directory_record.rb +152 -0
  260. data/lib/omnizip/formats/iso/joliet.rb +204 -0
  261. data/lib/omnizip/formats/iso/path_table.rb +125 -0
  262. data/lib/omnizip/formats/iso/reader.rb +197 -0
  263. data/lib/omnizip/formats/iso/rock_ridge.rb +349 -0
  264. data/lib/omnizip/formats/iso/volume_builder.rb +320 -0
  265. data/lib/omnizip/formats/iso/volume_descriptor.rb +168 -0
  266. data/lib/omnizip/formats/iso/writer.rb +530 -0
  267. data/lib/omnizip/formats/iso.rb +140 -0
  268. data/lib/omnizip/formats/lzip.rb +175 -0
  269. data/lib/omnizip/formats/lzma_alone.rb +171 -0
  270. data/lib/omnizip/formats/rar/archive_repairer.rb +243 -0
  271. data/lib/omnizip/formats/rar/archive_verifier.rb +195 -0
  272. data/lib/omnizip/formats/rar/block_parser.rb +243 -0
  273. data/lib/omnizip/formats/rar/compression/bit_stream.rb +180 -0
  274. data/lib/omnizip/formats/rar/compression/dispatcher.rb +217 -0
  275. data/lib/omnizip/formats/rar/compression/lz77_huffman/decoder.rb +216 -0
  276. data/lib/omnizip/formats/rar/compression/lz77_huffman/encoder.rb +158 -0
  277. data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_builder.rb +217 -0
  278. data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_coder.rb +189 -0
  279. data/lib/omnizip/formats/rar/compression/lz77_huffman/match_finder.rb +135 -0
  280. data/lib/omnizip/formats/rar/compression/lz77_huffman/sliding_window.rb +165 -0
  281. data/lib/omnizip/formats/rar/compression/ppmd/context.rb +105 -0
  282. data/lib/omnizip/formats/rar/compression/ppmd/decoder.rb +219 -0
  283. data/lib/omnizip/formats/rar/compression/ppmd/encoder.rb +262 -0
  284. data/lib/omnizip/formats/rar/compression_method_registry.rb +106 -0
  285. data/lib/omnizip/formats/rar/constants.rb +82 -0
  286. data/lib/omnizip/formats/rar/decompressor.rb +238 -0
  287. data/lib/omnizip/formats/rar/external_writer.rb +312 -0
  288. data/lib/omnizip/formats/rar/header.rb +192 -0
  289. data/lib/omnizip/formats/rar/license_validator.rb +109 -0
  290. data/lib/omnizip/formats/rar/models/rar_archive.rb +77 -0
  291. data/lib/omnizip/formats/rar/models/rar_entry.rb +65 -0
  292. data/lib/omnizip/formats/rar/models/rar_volume.rb +56 -0
  293. data/lib/omnizip/formats/rar/parity_handler.rb +292 -0
  294. data/lib/omnizip/formats/rar/rar5/compression/lzma.rb +202 -0
  295. data/lib/omnizip/formats/rar/rar5/compression/lzss.rb +578 -0
  296. data/lib/omnizip/formats/rar/rar5/compression/store.rb +60 -0
  297. data/lib/omnizip/formats/rar/rar5/crc32.rb +39 -0
  298. data/lib/omnizip/formats/rar/rar5/encryption/aes256_cbc.rb +97 -0
  299. data/lib/omnizip/formats/rar/rar5/encryption/encryption_header.rb +114 -0
  300. data/lib/omnizip/formats/rar/rar5/encryption/encryption_manager.rb +166 -0
  301. data/lib/omnizip/formats/rar/rar5/encryption/key_derivation.rb +97 -0
  302. data/lib/omnizip/formats/rar/rar5/header.rb +187 -0
  303. data/lib/omnizip/formats/rar/rar5/models/encryption_options.rb +74 -0
  304. data/lib/omnizip/formats/rar/rar5/models/recovery_options.rb +63 -0
  305. data/lib/omnizip/formats/rar/rar5/models/solid_options.rb +63 -0
  306. data/lib/omnizip/formats/rar/rar5/models/volume_options.rb +74 -0
  307. data/lib/omnizip/formats/rar/rar5/multi_volume/ARCHITECTURE.md +290 -0
  308. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_manager.rb +264 -0
  309. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_splitter.rb +155 -0
  310. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb +194 -0
  311. data/lib/omnizip/formats/rar/rar5/solid/solid_encoder.rb +109 -0
  312. data/lib/omnizip/formats/rar/rar5/solid/solid_manager.rb +142 -0
  313. data/lib/omnizip/formats/rar/rar5/solid/solid_stream.rb +121 -0
  314. data/lib/omnizip/formats/rar/rar5/vint.rb +65 -0
  315. data/lib/omnizip/formats/rar/rar5/writer.rb +466 -0
  316. data/lib/omnizip/formats/rar/rar_format_base.rb +241 -0
  317. data/lib/omnizip/formats/rar/reader.rb +366 -0
  318. data/lib/omnizip/formats/rar/recovery_record.rb +245 -0
  319. data/lib/omnizip/formats/rar/volume_manager.rb +168 -0
  320. data/lib/omnizip/formats/rar/writer.rb +431 -0
  321. data/lib/omnizip/formats/rar.rb +205 -0
  322. data/lib/omnizip/formats/rar3/compressor.rb +73 -0
  323. data/lib/omnizip/formats/rar3/decompressor.rb +66 -0
  324. data/lib/omnizip/formats/rar3/reader.rb +386 -0
  325. data/lib/omnizip/formats/rar3/writer.rb +219 -0
  326. data/lib/omnizip/formats/rar5/compressor.rb +73 -0
  327. data/lib/omnizip/formats/rar5/decompressor.rb +66 -0
  328. data/lib/omnizip/formats/rar5/reader.rb +342 -0
  329. data/lib/omnizip/formats/rar5/writer.rb +214 -0
  330. data/lib/omnizip/formats/seven_zip/coder_chain.rb +150 -0
  331. data/lib/omnizip/formats/seven_zip/constants.rb +126 -0
  332. data/lib/omnizip/formats/seven_zip/encoded_header.rb +114 -0
  333. data/lib/omnizip/formats/seven_zip/encrypted_header.rb +142 -0
  334. data/lib/omnizip/formats/seven_zip/file_collector.rb +144 -0
  335. data/lib/omnizip/formats/seven_zip/header.rb +106 -0
  336. data/lib/omnizip/formats/seven_zip/header_encryptor.rb +134 -0
  337. data/lib/omnizip/formats/seven_zip/header_writer.rb +466 -0
  338. data/lib/omnizip/formats/seven_zip/models/coder_info.rb +30 -0
  339. data/lib/omnizip/formats/seven_zip/models/file_entry.rb +58 -0
  340. data/lib/omnizip/formats/seven_zip/models/folder.rb +69 -0
  341. data/lib/omnizip/formats/seven_zip/models/stream_info.rb +42 -0
  342. data/lib/omnizip/formats/seven_zip/parser.rb +660 -0
  343. data/lib/omnizip/formats/seven_zip/reader.rb +458 -0
  344. data/lib/omnizip/formats/seven_zip/split_archive_reader.rb +632 -0
  345. data/lib/omnizip/formats/seven_zip/split_archive_writer.rb +315 -0
  346. data/lib/omnizip/formats/seven_zip/stream_compressor.rb +151 -0
  347. data/lib/omnizip/formats/seven_zip/stream_decompressor.rb +162 -0
  348. data/lib/omnizip/formats/seven_zip/writer.rb +740 -0
  349. data/lib/omnizip/formats/seven_zip.rb +93 -0
  350. data/lib/omnizip/formats/tar/constants.rb +73 -0
  351. data/lib/omnizip/formats/tar/entry.rb +94 -0
  352. data/lib/omnizip/formats/tar/header.rb +168 -0
  353. data/lib/omnizip/formats/tar/reader.rb +121 -0
  354. data/lib/omnizip/formats/tar/writer.rb +216 -0
  355. data/lib/omnizip/formats/tar.rb +84 -0
  356. data/lib/omnizip/formats/xz/reader.rb +116 -0
  357. data/lib/omnizip/formats/xz.rb +237 -0
  358. data/lib/omnizip/formats/xz_impl/block_decoder.rb +754 -0
  359. data/lib/omnizip/formats/xz_impl/block_encoder.rb +306 -0
  360. data/lib/omnizip/formats/xz_impl/block_header.rb +210 -0
  361. data/lib/omnizip/formats/xz_impl/block_header_parser.rb +186 -0
  362. data/lib/omnizip/formats/xz_impl/constants.rb +49 -0
  363. data/lib/omnizip/formats/xz_impl/index_decoder.rb +174 -0
  364. data/lib/omnizip/formats/xz_impl/index_encoder.rb +122 -0
  365. data/lib/omnizip/formats/xz_impl/stream_decoder.rb +468 -0
  366. data/lib/omnizip/formats/xz_impl/stream_encoder.rb +99 -0
  367. data/lib/omnizip/formats/xz_impl/stream_footer.rb +81 -0
  368. data/lib/omnizip/formats/xz_impl/stream_footer_parser.rb +117 -0
  369. data/lib/omnizip/formats/xz_impl/stream_header.rb +55 -0
  370. data/lib/omnizip/formats/xz_impl/stream_header_parser.rb +108 -0
  371. data/lib/omnizip/formats/xz_impl/vli.rb +128 -0
  372. data/lib/omnizip/formats/xz_impl/writer.rb +421 -0
  373. data/lib/omnizip/formats/zip/central_directory_header.rb +195 -0
  374. data/lib/omnizip/formats/zip/constants.rb +69 -0
  375. data/lib/omnizip/formats/zip/end_of_central_directory.rb +133 -0
  376. data/lib/omnizip/formats/zip/local_file_header.rb +138 -0
  377. data/lib/omnizip/formats/zip/reader.rb +250 -0
  378. data/lib/omnizip/formats/zip/unix_extra_field.rb +153 -0
  379. data/lib/omnizip/formats/zip/writer.rb +375 -0
  380. data/lib/omnizip/formats/zip/zip64_end_of_central_directory.rb +104 -0
  381. data/lib/omnizip/formats/zip/zip64_end_of_central_directory_locator.rb +66 -0
  382. data/lib/omnizip/formats/zip/zip64_extra_field.rb +114 -0
  383. data/lib/omnizip/formats/zip.rb +50 -0
  384. data/lib/omnizip/implementations/base/lzma2_decoder_base.rb +75 -0
  385. data/lib/omnizip/implementations/base/lzma2_encoder_base.rb +128 -0
  386. data/lib/omnizip/implementations/base/lzma_decoder_base.rb +83 -0
  387. data/lib/omnizip/implementations/base/lzma_encoder_base.rb +108 -0
  388. data/lib/omnizip/implementations/base/state_machine_base.rb +182 -0
  389. data/lib/omnizip/implementations/seven_zip/lzma/decoder.rb +421 -0
  390. data/lib/omnizip/implementations/seven_zip/lzma/encoder.rb +465 -0
  391. data/lib/omnizip/implementations/seven_zip/lzma/match_finder.rb +288 -0
  392. data/lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb +200 -0
  393. data/lib/omnizip/implementations/seven_zip/lzma/range_encoder.rb +197 -0
  394. data/lib/omnizip/implementations/seven_zip/lzma/state_machine.rb +141 -0
  395. data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +519 -0
  396. data/lib/omnizip/implementations/xz_utils/lzma2/decoder.rb +723 -0
  397. data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +750 -0
  398. data/lib/omnizip/io/buffered_input.rb +146 -0
  399. data/lib/omnizip/io/buffered_output.rb +105 -0
  400. data/lib/omnizip/io/stream_manager.rb +115 -0
  401. data/lib/omnizip/link_handler/hard_link.rb +79 -0
  402. data/lib/omnizip/link_handler/symbolic_link.rb +74 -0
  403. data/lib/omnizip/link_handler.rb +124 -0
  404. data/lib/omnizip/metadata/archive_metadata.rb +114 -0
  405. data/lib/omnizip/metadata/entry_metadata.rb +146 -0
  406. data/lib/omnizip/metadata/metadata_editor.rb +171 -0
  407. data/lib/omnizip/metadata/metadata_registry.rb +64 -0
  408. data/lib/omnizip/metadata/metadata_validator.rb +99 -0
  409. data/lib/omnizip/metadata.rb +57 -0
  410. data/lib/omnizip/models/.keep +0 -0
  411. data/lib/omnizip/models/algorithm_metadata.rb +73 -0
  412. data/lib/omnizip/models/compression_options.rb +71 -0
  413. data/lib/omnizip/models/conversion_options.rb +87 -0
  414. data/lib/omnizip/models/conversion_result.rb +135 -0
  415. data/lib/omnizip/models/eta_result.rb +46 -0
  416. data/lib/omnizip/models/extraction_rule.rb +115 -0
  417. data/lib/omnizip/models/filter_chain.rb +144 -0
  418. data/lib/omnizip/models/filter_config.rb +183 -0
  419. data/lib/omnizip/models/match_result.rb +124 -0
  420. data/lib/omnizip/models/optimization_suggestion.rb +91 -0
  421. data/lib/omnizip/models/parallel_options.rb +104 -0
  422. data/lib/omnizip/models/performance_result.rb +79 -0
  423. data/lib/omnizip/models/profile_report.rb +82 -0
  424. data/lib/omnizip/models/progress_options.rb +38 -0
  425. data/lib/omnizip/models/split_options.rb +116 -0
  426. data/lib/omnizip/optimization_registry.rb +81 -0
  427. data/lib/omnizip/parallel/job_queue.rb +209 -0
  428. data/lib/omnizip/parallel/job_scheduler.rb +203 -0
  429. data/lib/omnizip/parallel/parallel_compressor.rb +347 -0
  430. data/lib/omnizip/parallel/parallel_extractor.rb +329 -0
  431. data/lib/omnizip/parallel/worker_pool.rb +223 -0
  432. data/lib/omnizip/parallel.rb +149 -0
  433. data/lib/omnizip/parity/chunked_block_processor.rb +196 -0
  434. data/lib/omnizip/parity/galois16.rb +145 -0
  435. data/lib/omnizip/parity/models/creator_packet.rb +73 -0
  436. data/lib/omnizip/parity/models/file_description_packet.rb +133 -0
  437. data/lib/omnizip/parity/models/ifsc_packet.rb +123 -0
  438. data/lib/omnizip/parity/models/main_packet.rb +128 -0
  439. data/lib/omnizip/parity/models/packet.rb +156 -0
  440. data/lib/omnizip/parity/models/packet_registry.rb +109 -0
  441. data/lib/omnizip/parity/models/recovery_slice_packet.rb +78 -0
  442. data/lib/omnizip/parity/par2_creator.rb +531 -0
  443. data/lib/omnizip/parity/par2_repairer.rb +407 -0
  444. data/lib/omnizip/parity/par2_verifier.rb +364 -0
  445. data/lib/omnizip/parity/par2cmdline_algorithm.rb +110 -0
  446. data/lib/omnizip/parity/par2cmdline_coefficients.rb +78 -0
  447. data/lib/omnizip/parity/reed_solomon_decoder.rb +266 -0
  448. data/lib/omnizip/parity/reed_solomon_encoder.rb +111 -0
  449. data/lib/omnizip/parity/reed_solomon_matrix.rb +342 -0
  450. data/lib/omnizip/parity.rb +186 -0
  451. data/lib/omnizip/password/encryption_registry.rb +65 -0
  452. data/lib/omnizip/password/encryption_strategy.rb +96 -0
  453. data/lib/omnizip/password/password_validator.rb +129 -0
  454. data/lib/omnizip/password/winzip_aes_strategy.rb +192 -0
  455. data/lib/omnizip/password/zip_crypto_strategy.rb +141 -0
  456. data/lib/omnizip/password.rb +87 -0
  457. data/lib/omnizip/pipe/stream_compressor.rb +124 -0
  458. data/lib/omnizip/pipe/stream_decompressor.rb +174 -0
  459. data/lib/omnizip/pipe.rb +121 -0
  460. data/lib/omnizip/platform/ntfs_streams.rb +201 -0
  461. data/lib/omnizip/platform.rb +189 -0
  462. data/lib/omnizip/profile/archive_profile.rb +39 -0
  463. data/lib/omnizip/profile/balanced_profile.rb +33 -0
  464. data/lib/omnizip/profile/binary_profile.rb +36 -0
  465. data/lib/omnizip/profile/compression_profile.rb +158 -0
  466. data/lib/omnizip/profile/custom_profile.rb +157 -0
  467. data/lib/omnizip/profile/fast_profile.rb +33 -0
  468. data/lib/omnizip/profile/maximum_profile.rb +33 -0
  469. data/lib/omnizip/profile/profile_detector.rb +110 -0
  470. data/lib/omnizip/profile/profile_registry.rb +161 -0
  471. data/lib/omnizip/profile/text_profile.rb +36 -0
  472. data/lib/omnizip/profile.rb +190 -0
  473. data/lib/omnizip/profiler/memory_profiler.rb +66 -0
  474. data/lib/omnizip/profiler/method_profiler.rb +49 -0
  475. data/lib/omnizip/profiler/report_generator.rb +169 -0
  476. data/lib/omnizip/profiler.rb +204 -0
  477. data/lib/omnizip/progress/callback_reporter.rb +36 -0
  478. data/lib/omnizip/progress/console_reporter.rb +62 -0
  479. data/lib/omnizip/progress/log_reporter.rb +91 -0
  480. data/lib/omnizip/progress/operation_progress.rb +118 -0
  481. data/lib/omnizip/progress/progress_bar.rb +156 -0
  482. data/lib/omnizip/progress/progress_reporter.rb +40 -0
  483. data/lib/omnizip/progress/progress_tracker.rb +190 -0
  484. data/lib/omnizip/progress/silent_reporter.rb +24 -0
  485. data/lib/omnizip/progress.rb +127 -0
  486. data/lib/omnizip/rubyzip_compat.rb +63 -0
  487. data/lib/omnizip/temp/safe_extract.rb +168 -0
  488. data/lib/omnizip/temp/temp_file.rb +124 -0
  489. data/lib/omnizip/temp/temp_file_pool.rb +109 -0
  490. data/lib/omnizip/temp.rb +181 -0
  491. data/lib/omnizip/version.rb +5 -0
  492. data/lib/omnizip/zip/entry.rb +156 -0
  493. data/lib/omnizip/zip/file.rb +485 -0
  494. data/lib/omnizip/zip/input_stream.rb +273 -0
  495. data/lib/omnizip/zip/output_stream.rb +324 -0
  496. data/lib/omnizip.rb +156 -0
  497. data/readme-docs/advanced-features.adoc +515 -0
  498. data/readme-docs/api-usage.adoc +444 -0
  499. data/readme-docs/architecture.adoc +449 -0
  500. data/readme-docs/archive-formats.adoc +479 -0
  501. data/readme-docs/cli-usage.adoc +222 -0
  502. data/readme-docs/compression-algorithms.adoc +442 -0
  503. data/readme-docs/compression-profiles.adoc +247 -0
  504. data/readme-docs/encryption-checksums.adoc +328 -0
  505. data/readme-docs/format-converter.adoc +325 -0
  506. data/readme-docs/installation.adoc +228 -0
  507. data/readme-docs/par2-archives.adoc +608 -0
  508. data/readme-docs/performance-profiler.adoc +389 -0
  509. data/readme-docs/preprocessing-filters.adoc +280 -0
  510. data/xz-file-format-1.2.1.txt +1174 -0
  511. 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