omnizip 0.4.7-x86_64-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (632) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +32 -0
  4. data/.rubocop_todo.yml +293 -0
  5. data/CHANGELOG.md +1647 -0
  6. data/CONTEXT.md +68 -0
  7. data/COPYING +502 -0
  8. data/Gemfile +19 -0
  9. data/LICENSE +12 -0
  10. data/README.adoc +1327 -0
  11. data/Rakefile +15 -0
  12. data/TODO.refactor/00-overview.md +67 -0
  13. data/TODO.refactor/01-registry-base-class.md +81 -0
  14. data/TODO.refactor/02-error-hierarchy.md +57 -0
  15. data/TODO.refactor/03-autoload-entry-point.md +69 -0
  16. data/TODO.refactor/04-filter-base-consolidation.md +49 -0
  17. data/TODO.refactor/05-send-private-methods.md +64 -0
  18. data/TODO.refactor/06-instance-variable-access.md +69 -0
  19. data/TODO.refactor/07-respond-to-replacement.md +237 -0
  20. data/TODO.refactor/08-spec-doubles.md +27 -0
  21. data/TODO.refactor/09-cli-shared-module.md +35 -0
  22. data/TODO.refactor/10-format-detector-ocp.md +34 -0
  23. data/TODO.refactor/11-convenience-decoupling.md +38 -0
  24. data/TODO.refactor/12-thread-safety.md +8 -0
  25. data/TODO.refactor/13-lutaml-model-migration.md +158 -0
  26. data/TODO.refactor/14-add-missing-specs.md +25 -0
  27. data/benchmark/README.md +260 -0
  28. data/benchmark/benchmark_suite.rb +125 -0
  29. data/benchmark/compression_bench.rb +181 -0
  30. data/benchmark/filter_bench.rb +180 -0
  31. data/benchmark/models/benchmark_result.rb +59 -0
  32. data/benchmark/models/comparison_result.rb +69 -0
  33. data/benchmark/profile_suite.rb +167 -0
  34. data/benchmark/reporter.rb +150 -0
  35. data/benchmark/run_benchmarks.rb +66 -0
  36. data/benchmark/test_data.rb +137 -0
  37. data/config/formats/rar3_spec.yml +92 -0
  38. data/config/formats/rar5_spec.yml +102 -0
  39. data/docs/.github/workflows/docs.yml +142 -0
  40. data/docs/.gitignore +21 -0
  41. data/docs/.lychee.toml +67 -0
  42. data/docs/Gemfile +13 -0
  43. data/docs/RAR_WRITE_SUPPORT.md +26 -0
  44. data/docs/README.md +101 -0
  45. data/docs/_config.yml +112 -0
  46. data/docs/assets/logo.svg +1 -0
  47. data/docs/assets/omnizip-logo.pdf +1540 -11
  48. data/docs/comparison/feature-matrix.adoc +694 -0
  49. data/docs/comparison/index.adoc +113 -0
  50. data/docs/comparison/vs-7zip.adoc +309 -0
  51. data/docs/comparison/vs-peazip.adoc +77 -0
  52. data/docs/comparison/vs-rubyzip.adoc +342 -0
  53. data/docs/comparison/vs-winrar.adoc +100 -0
  54. data/docs/compatibility.adoc +579 -0
  55. data/docs/concepts/index.adoc +129 -0
  56. data/docs/developer/architecture.adoc +256 -0
  57. data/docs/developer/contributing.adoc +158 -0
  58. data/docs/developer/index.adoc +25 -0
  59. data/docs/developer/testing.adoc +212 -0
  60. data/docs/getting-started/basic-usage.adoc +263 -0
  61. data/docs/getting-started/index.adoc +42 -0
  62. data/docs/getting-started/installation.adoc +138 -0
  63. data/docs/getting-started/quick-start.adoc +183 -0
  64. data/docs/getting-started/your-first-archive.adoc +219 -0
  65. data/docs/guides/advanced-features/encryption.adoc +277 -0
  66. data/docs/guides/advanced-features/index.adoc +59 -0
  67. data/docs/guides/advanced-features/parallel-processing.adoc +144 -0
  68. data/docs/guides/advanced-features/progress-tracking.adoc +124 -0
  69. data/docs/guides/advanced-features/streaming.adoc +142 -0
  70. data/docs/guides/archive-formats/gzip-format.adoc +105 -0
  71. data/docs/guides/archive-formats/index.adoc +160 -0
  72. data/docs/guides/archive-formats/ole-format.adoc +151 -0
  73. data/docs/guides/archive-formats/rar-format.adoc +104 -0
  74. data/docs/guides/archive-formats/rar5.adoc +521 -0
  75. data/docs/guides/archive-formats/rpm-format.adoc +108 -0
  76. data/docs/guides/archive-formats/seven-zip-format.adoc +35 -0
  77. data/docs/guides/archive-formats/tar-format.adoc +106 -0
  78. data/docs/guides/archive-formats/xz-format.adoc +118 -0
  79. data/docs/guides/archive-formats/zip-format.adoc +35 -0
  80. data/docs/guides/compression-algorithms/bzip2.adoc +114 -0
  81. data/docs/guides/compression-algorithms/deflate.adoc +313 -0
  82. data/docs/guides/compression-algorithms/index.adoc +190 -0
  83. data/docs/guides/compression-algorithms/lzma.adoc +394 -0
  84. data/docs/guides/compression-algorithms/lzma2.adoc +244 -0
  85. data/docs/guides/compression-algorithms/ppmd.adoc +313 -0
  86. data/docs/guides/compression-algorithms/zstandard.adoc +296 -0
  87. data/docs/guides/creating-archives.adoc +348 -0
  88. data/docs/guides/extracting-archives.adoc +53 -0
  89. data/docs/guides/format-conversion.adoc +64 -0
  90. data/docs/guides/index.adoc +49 -0
  91. data/docs/guides/migration-rubyzip.adoc +217 -0
  92. data/docs/guides/parity-archives.adoc +605 -0
  93. data/docs/guides/performance-tuning.adoc +88 -0
  94. data/docs/index.adoc +228 -0
  95. data/docs/lychee.toml +67 -0
  96. data/docs/reference/api/overview.adoc +187 -0
  97. data/docs/reference/cli/compress-command.adoc +114 -0
  98. data/docs/reference/cli/overview.adoc +140 -0
  99. data/docs/reference/index.adoc +26 -0
  100. data/docs/resources/faq.adoc +185 -0
  101. data/docs/resources/quick-reference.adoc +222 -0
  102. data/docs/rust-backend.md +0 -0
  103. data/docs/troubleshooting/index.adoc +207 -0
  104. data/docs/xar_format.md +216 -0
  105. data/examples/api_comparison.rb +205 -0
  106. data/examples/deflate64_example.rb +96 -0
  107. data/examples/par2_demo.rb +121 -0
  108. data/examples/quick_start_native.rb +150 -0
  109. data/examples/quick_start_rubyzip.rb +115 -0
  110. data/examples/rubyzip_compatibility_demo.rb +194 -0
  111. data/exe/omnizip +27 -0
  112. data/lib/omnizip/algorithm.rb +176 -0
  113. data/lib/omnizip/algorithm_registry.rb +65 -0
  114. data/lib/omnizip/algorithms/.keep +0 -0
  115. data/lib/omnizip/algorithms/bzip2/bwt.rb +236 -0
  116. data/lib/omnizip/algorithms/bzip2/bz2.rb +687 -0
  117. data/lib/omnizip/algorithms/bzip2/rle.rb +146 -0
  118. data/lib/omnizip/algorithms/bzip2.rb +108 -0
  119. data/lib/omnizip/algorithms/deflate/constants.rb +28 -0
  120. data/lib/omnizip/algorithms/deflate/decoder.rb +37 -0
  121. data/lib/omnizip/algorithms/deflate/encoder.rb +45 -0
  122. data/lib/omnizip/algorithms/deflate.rb +135 -0
  123. data/lib/omnizip/algorithms/deflate64/constants.rb +45 -0
  124. data/lib/omnizip/algorithms/deflate64/decoder.rb +151 -0
  125. data/lib/omnizip/algorithms/deflate64/encoder.rb +95 -0
  126. data/lib/omnizip/algorithms/deflate64/huffman_coder.rb +352 -0
  127. data/lib/omnizip/algorithms/deflate64/lz77_encoder.rb +140 -0
  128. data/lib/omnizip/algorithms/deflate64.rb +118 -0
  129. data/lib/omnizip/algorithms/lzma/bit_model.rb +120 -0
  130. data/lib/omnizip/algorithms/lzma/constants.rb +112 -0
  131. data/lib/omnizip/algorithms/lzma/decoder.rb +146 -0
  132. data/lib/omnizip/algorithms/lzma/dictionary.rb +70 -0
  133. data/lib/omnizip/algorithms/lzma/distance_coder.rb +326 -0
  134. data/lib/omnizip/algorithms/lzma/encoder.rb +139 -0
  135. data/lib/omnizip/algorithms/lzma/length_coder.rb +172 -0
  136. data/lib/omnizip/algorithms/lzma/literal_decoder.rb +204 -0
  137. data/lib/omnizip/algorithms/lzma/literal_encoder.rb +208 -0
  138. data/lib/omnizip/algorithms/lzma/lzip_decoder.rb +368 -0
  139. data/lib/omnizip/algorithms/lzma/lzma1_encoder.rb +105 -0
  140. data/lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb +194 -0
  141. data/lib/omnizip/algorithms/lzma/lzma_state.rb +128 -0
  142. data/lib/omnizip/algorithms/lzma/match.rb +32 -0
  143. data/lib/omnizip/algorithms/lzma/match_finder.rb +233 -0
  144. data/lib/omnizip/algorithms/lzma/match_finder_config.rb +142 -0
  145. data/lib/omnizip/algorithms/lzma/match_finder_factory.rb +84 -0
  146. data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +159 -0
  147. data/lib/omnizip/algorithms/lzma/probability_models.rb +72 -0
  148. data/lib/omnizip/algorithms/lzma/range_coder.rb +82 -0
  149. data/lib/omnizip/algorithms/lzma/range_decoder.rb +274 -0
  150. data/lib/omnizip/algorithms/lzma/range_encoder.rb +202 -0
  151. data/lib/omnizip/algorithms/lzma/state.rb +127 -0
  152. data/lib/omnizip/algorithms/lzma/xz_buffered_range_encoder.rb +323 -0
  153. data/lib/omnizip/algorithms/lzma/xz_encoder.rb +420 -0
  154. data/lib/omnizip/algorithms/lzma/xz_encoder_fast.rb +640 -0
  155. data/lib/omnizip/algorithms/lzma/xz_match_finder_adapter.rb +224 -0
  156. data/lib/omnizip/algorithms/lzma/xz_price_calculator.rb +167 -0
  157. data/lib/omnizip/algorithms/lzma/xz_probability_models.rb +258 -0
  158. data/lib/omnizip/algorithms/lzma/xz_range_encoder.rb +223 -0
  159. data/lib/omnizip/algorithms/lzma/xz_range_encoder_exact.rb +314 -0
  160. data/lib/omnizip/algorithms/lzma/xz_state.rb +108 -0
  161. data/lib/omnizip/algorithms/lzma/xz_utils_decoder.rb +1311 -0
  162. data/lib/omnizip/algorithms/lzma.rb +266 -0
  163. data/lib/omnizip/algorithms/lzma2/chunk_manager.rb +180 -0
  164. data/lib/omnizip/algorithms/lzma2/constants.rb +38 -0
  165. data/lib/omnizip/algorithms/lzma2/encoder.rb +145 -0
  166. data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +165 -0
  167. data/lib/omnizip/algorithms/lzma2/properties.rb +179 -0
  168. data/lib/omnizip/algorithms/lzma2/simple_lzma2_encoder.rb +122 -0
  169. data/lib/omnizip/algorithms/lzma2/xz_encoder_adapter.rb +85 -0
  170. data/lib/omnizip/algorithms/lzma2.rb +133 -0
  171. data/lib/omnizip/algorithms/ppmd7/constants.rb +74 -0
  172. data/lib/omnizip/algorithms/ppmd7/context.rb +151 -0
  173. data/lib/omnizip/algorithms/ppmd7/decoder.rb +127 -0
  174. data/lib/omnizip/algorithms/ppmd7/encoder.rb +153 -0
  175. data/lib/omnizip/algorithms/ppmd7/model.rb +245 -0
  176. data/lib/omnizip/algorithms/ppmd7/symbol_state.rb +57 -0
  177. data/lib/omnizip/algorithms/ppmd7.rb +146 -0
  178. data/lib/omnizip/algorithms/ppmd8/constants.rb +61 -0
  179. data/lib/omnizip/algorithms/ppmd8/context.rb +32 -0
  180. data/lib/omnizip/algorithms/ppmd8/decoder.rb +104 -0
  181. data/lib/omnizip/algorithms/ppmd8/encoder.rb +135 -0
  182. data/lib/omnizip/algorithms/ppmd8/model.rb +246 -0
  183. data/lib/omnizip/algorithms/ppmd8/restoration_method.rb +78 -0
  184. data/lib/omnizip/algorithms/ppmd8.rb +122 -0
  185. data/lib/omnizip/algorithms/ppmd_base.rb +142 -0
  186. data/lib/omnizip/algorithms/registration.rb +28 -0
  187. data/lib/omnizip/algorithms/zstandard/constants.rb +158 -0
  188. data/lib/omnizip/algorithms/zstandard/decoder.rb +249 -0
  189. data/lib/omnizip/algorithms/zstandard/dictionary.rb +73 -0
  190. data/lib/omnizip/algorithms/zstandard/encoder.rb +294 -0
  191. data/lib/omnizip/algorithms/zstandard/frame/block.rb +143 -0
  192. data/lib/omnizip/algorithms/zstandard/frame/header.rb +233 -0
  193. data/lib/omnizip/algorithms/zstandard/frame.rb +33 -0
  194. data/lib/omnizip/algorithms/zstandard/fse/bitstream.rb +183 -0
  195. data/lib/omnizip/algorithms/zstandard/fse/encoder.rb +534 -0
  196. data/lib/omnizip/algorithms/zstandard/fse/interleaved.rb +92 -0
  197. data/lib/omnizip/algorithms/zstandard/fse/table.rb +188 -0
  198. data/lib/omnizip/algorithms/zstandard/fse/table_description.rb +203 -0
  199. data/lib/omnizip/algorithms/zstandard/fse.rb +53 -0
  200. data/lib/omnizip/algorithms/zstandard/huffman.rb +276 -0
  201. data/lib/omnizip/algorithms/zstandard/huffman_encoder.rb +327 -0
  202. data/lib/omnizip/algorithms/zstandard/ldm.rb +121 -0
  203. data/lib/omnizip/algorithms/zstandard/literals.rb +241 -0
  204. data/lib/omnizip/algorithms/zstandard/literals_encoder.rb +96 -0
  205. data/lib/omnizip/algorithms/zstandard/match_finder.rb +483 -0
  206. data/lib/omnizip/algorithms/zstandard/sequences.rb +350 -0
  207. data/lib/omnizip/algorithms/zstandard/sequences_encoder.rb +333 -0
  208. data/lib/omnizip/algorithms/zstandard/xxhash.rb +159 -0
  209. data/lib/omnizip/algorithms/zstandard.rb +210 -0
  210. data/lib/omnizip/algorithms.rb +35 -0
  211. data/lib/omnizip/archive/builder.rb +48 -0
  212. data/lib/omnizip/archive/reader_session.rb +67 -0
  213. data/lib/omnizip/archive.rb +86 -0
  214. data/lib/omnizip/archive_handler.rb +82 -0
  215. data/lib/omnizip/archive_handlers/cpio_handler.rb +47 -0
  216. data/lib/omnizip/archive_handlers/iso_handler.rb +54 -0
  217. data/lib/omnizip/archive_handlers/ole_handler.rb +37 -0
  218. data/lib/omnizip/archive_handlers/rar_handler.rb +96 -0
  219. data/lib/omnizip/archive_handlers/rpm_handler.rb +45 -0
  220. data/lib/omnizip/archive_handlers/seven_zip_handler.rb +89 -0
  221. data/lib/omnizip/archive_handlers/tar_handler.rb +75 -0
  222. data/lib/omnizip/archive_handlers/xar_handler.rb +49 -0
  223. data/lib/omnizip/archive_handlers/zip_handler.rb +115 -0
  224. data/lib/omnizip/archive_handlers.rb +18 -0
  225. data/lib/omnizip/backends.rb +160 -0
  226. data/lib/omnizip/buffer/memory_archive.rb +246 -0
  227. data/lib/omnizip/buffer/memory_extractor.rb +234 -0
  228. data/lib/omnizip/buffer/seven_zip_bridge.rb +171 -0
  229. data/lib/omnizip/buffer.rb +187 -0
  230. data/lib/omnizip/checksum_registry.rb +41 -0
  231. data/lib/omnizip/checksums/crc32.rb +101 -0
  232. data/lib/omnizip/checksums/crc64.rb +102 -0
  233. data/lib/omnizip/checksums/crc_base.rb +158 -0
  234. data/lib/omnizip/checksums/registration.rb +16 -0
  235. data/lib/omnizip/checksums/verifier.rb +130 -0
  236. data/lib/omnizip/checksums.rb +11 -0
  237. data/lib/omnizip/chunked/memory_manager.rb +194 -0
  238. data/lib/omnizip/chunked/reader.rb +78 -0
  239. data/lib/omnizip/chunked/writer.rb +123 -0
  240. data/lib/omnizip/chunked.rb +123 -0
  241. data/lib/omnizip/cli/output_formatter.rb +112 -0
  242. data/lib/omnizip/cli.rb +604 -0
  243. data/lib/omnizip/commands/.keep +0 -0
  244. data/lib/omnizip/commands/archive_create_command.rb +245 -0
  245. data/lib/omnizip/commands/archive_extract_command.rb +231 -0
  246. data/lib/omnizip/commands/archive_list_command.rb +204 -0
  247. data/lib/omnizip/commands/archive_repair_command.rb +129 -0
  248. data/lib/omnizip/commands/archive_verify_command.rb +115 -0
  249. data/lib/omnizip/commands/compress_command.rb +115 -0
  250. data/lib/omnizip/commands/decompress_command.rb +149 -0
  251. data/lib/omnizip/commands/list_command.rb +51 -0
  252. data/lib/omnizip/commands/metadata_command.rb +215 -0
  253. data/lib/omnizip/commands/parity_create_command.rb +114 -0
  254. data/lib/omnizip/commands/parity_repair_command.rb +120 -0
  255. data/lib/omnizip/commands/parity_verify_command.rb +122 -0
  256. data/lib/omnizip/commands/profile_list_command.rb +54 -0
  257. data/lib/omnizip/commands/profile_show_command.rb +44 -0
  258. data/lib/omnizip/commands.rb +21 -0
  259. data/lib/omnizip/convenience.rb +389 -0
  260. data/lib/omnizip/converter/conversion_registry.rb +50 -0
  261. data/lib/omnizip/converter/conversion_strategy.rb +108 -0
  262. data/lib/omnizip/converter/extract_repack_strategy.rb +51 -0
  263. data/lib/omnizip/converter/seven_zip_to_zip_strategy.rb +43 -0
  264. data/lib/omnizip/converter/zip_to_seven_zip_strategy.rb +54 -0
  265. data/lib/omnizip/converter.rb +124 -0
  266. data/lib/omnizip/crypto/aes256/cipher.rb +104 -0
  267. data/lib/omnizip/crypto/aes256/constants.rb +28 -0
  268. data/lib/omnizip/crypto/aes256/key_derivation.rb +100 -0
  269. data/lib/omnizip/crypto/aes256.rb +102 -0
  270. data/lib/omnizip/crypto.rb +11 -0
  271. data/lib/omnizip/entry.rb +44 -0
  272. data/lib/omnizip/error.rb +110 -0
  273. data/lib/omnizip/eta/exponential_smoothing_estimator.rb +95 -0
  274. data/lib/omnizip/eta/moving_average_estimator.rb +96 -0
  275. data/lib/omnizip/eta/rate_calculator.rb +104 -0
  276. data/lib/omnizip/eta/sample_history.rb +143 -0
  277. data/lib/omnizip/eta/time_estimator.rb +106 -0
  278. data/lib/omnizip/eta.rb +68 -0
  279. data/lib/omnizip/extraction/filter_chain.rb +179 -0
  280. data/lib/omnizip/extraction/glob_pattern.rb +140 -0
  281. data/lib/omnizip/extraction/pattern_matcher.rb +66 -0
  282. data/lib/omnizip/extraction/predicate_pattern.rb +52 -0
  283. data/lib/omnizip/extraction/regex_pattern.rb +50 -0
  284. data/lib/omnizip/extraction/selective_extractor.rb +247 -0
  285. data/lib/omnizip/extraction.rb +115 -0
  286. data/lib/omnizip/file_type/mime_classifier.rb +144 -0
  287. data/lib/omnizip/file_type.rb +117 -0
  288. data/lib/omnizip/filter.rb +141 -0
  289. data/lib/omnizip/filter_pipeline.rb +108 -0
  290. data/lib/omnizip/filter_registry.rb +113 -0
  291. data/lib/omnizip/filters/bcj.rb +277 -0
  292. data/lib/omnizip/filters/bcj2/constants.rb +53 -0
  293. data/lib/omnizip/filters/bcj2/decoder.rb +263 -0
  294. data/lib/omnizip/filters/bcj2/encoder.rb +58 -0
  295. data/lib/omnizip/filters/bcj2/stream_data.rb +91 -0
  296. data/lib/omnizip/filters/bcj2.rb +93 -0
  297. data/lib/omnizip/filters/bcj_arm.rb +174 -0
  298. data/lib/omnizip/filters/bcj_arm64.rb +242 -0
  299. data/lib/omnizip/filters/bcj_ia64.rb +194 -0
  300. data/lib/omnizip/filters/bcj_ppc.rb +188 -0
  301. data/lib/omnizip/filters/bcj_sparc.rb +174 -0
  302. data/lib/omnizip/filters/bcj_x86.rb +191 -0
  303. data/lib/omnizip/filters/delta.rb +195 -0
  304. data/lib/omnizip/filters/xz_delta.rb +258 -0
  305. data/lib/omnizip/filters.rb +20 -0
  306. data/lib/omnizip/format_detector.rb +166 -0
  307. data/lib/omnizip/formats/.keep +0 -0
  308. data/lib/omnizip/formats/bzip2_file.rb +159 -0
  309. data/lib/omnizip/formats/cpio/bounded_io.rb +66 -0
  310. data/lib/omnizip/formats/cpio/constants.rb +55 -0
  311. data/lib/omnizip/formats/cpio/entry.rb +389 -0
  312. data/lib/omnizip/formats/cpio/reader.rb +194 -0
  313. data/lib/omnizip/formats/cpio/writer.rb +232 -0
  314. data/lib/omnizip/formats/cpio.rb +132 -0
  315. data/lib/omnizip/formats/format_spec_loader.rb +228 -0
  316. data/lib/omnizip/formats/gzip.rb +236 -0
  317. data/lib/omnizip/formats/iso/directory_builder.rb +321 -0
  318. data/lib/omnizip/formats/iso/directory_record.rb +162 -0
  319. data/lib/omnizip/formats/iso/joliet.rb +204 -0
  320. data/lib/omnizip/formats/iso/path_table.rb +125 -0
  321. data/lib/omnizip/formats/iso/reader.rb +194 -0
  322. data/lib/omnizip/formats/iso/rock_ridge.rb +349 -0
  323. data/lib/omnizip/formats/iso/volume_builder.rb +319 -0
  324. data/lib/omnizip/formats/iso/volume_descriptor.rb +168 -0
  325. data/lib/omnizip/formats/iso/writer.rb +543 -0
  326. data/lib/omnizip/formats/iso.rb +133 -0
  327. data/lib/omnizip/formats/lzip.rb +161 -0
  328. data/lib/omnizip/formats/lzma_alone.rb +149 -0
  329. data/lib/omnizip/formats/msi/cab_extractor.rb +181 -0
  330. data/lib/omnizip/formats/msi/constants.rb +157 -0
  331. data/lib/omnizip/formats/msi/directory_resolver.rb +188 -0
  332. data/lib/omnizip/formats/msi/entry.rb +134 -0
  333. data/lib/omnizip/formats/msi/reader.rb +301 -0
  334. data/lib/omnizip/formats/msi/string_pool.rb +246 -0
  335. data/lib/omnizip/formats/msi/table_parser.rb +244 -0
  336. data/lib/omnizip/formats/msi.rb +73 -0
  337. data/lib/omnizip/formats/ole/allocation_table.rb +263 -0
  338. data/lib/omnizip/formats/ole/constants.rb +61 -0
  339. data/lib/omnizip/formats/ole/dirent.rb +439 -0
  340. data/lib/omnizip/formats/ole/header.rb +199 -0
  341. data/lib/omnizip/formats/ole/ranges_io.rb +347 -0
  342. data/lib/omnizip/formats/ole/storage.rb +482 -0
  343. data/lib/omnizip/formats/ole/types/variant.rb +338 -0
  344. data/lib/omnizip/formats/ole.rb +143 -0
  345. data/lib/omnizip/formats/rar/archive_repairer.rb +240 -0
  346. data/lib/omnizip/formats/rar/archive_verifier.rb +192 -0
  347. data/lib/omnizip/formats/rar/block_parser.rb +282 -0
  348. data/lib/omnizip/formats/rar/compression/bit_stream.rb +180 -0
  349. data/lib/omnizip/formats/rar/compression/dispatcher.rb +210 -0
  350. data/lib/omnizip/formats/rar/compression/lz77_huffman/decoder.rb +212 -0
  351. data/lib/omnizip/formats/rar/compression/lz77_huffman/encoder.rb +154 -0
  352. data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_builder.rb +217 -0
  353. data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_coder.rb +189 -0
  354. data/lib/omnizip/formats/rar/compression/lz77_huffman/match_finder.rb +135 -0
  355. data/lib/omnizip/formats/rar/compression/lz77_huffman/sliding_window.rb +165 -0
  356. data/lib/omnizip/formats/rar/compression/lz77_huffman.rb +25 -0
  357. data/lib/omnizip/formats/rar/compression/ppmd/context.rb +103 -0
  358. data/lib/omnizip/formats/rar/compression/ppmd/decoder.rb +238 -0
  359. data/lib/omnizip/formats/rar/compression/ppmd/encoder.rb +250 -0
  360. data/lib/omnizip/formats/rar/compression/ppmd.rb +16 -0
  361. data/lib/omnizip/formats/rar/compression.rb +17 -0
  362. data/lib/omnizip/formats/rar/compression_method_registry.rb +106 -0
  363. data/lib/omnizip/formats/rar/constants.rb +88 -0
  364. data/lib/omnizip/formats/rar/decompressor.rb +316 -0
  365. data/lib/omnizip/formats/rar/external_writer.rb +311 -0
  366. data/lib/omnizip/formats/rar/header.rb +209 -0
  367. data/lib/omnizip/formats/rar/license_validator.rb +111 -0
  368. data/lib/omnizip/formats/rar/models/rar_archive.rb +77 -0
  369. data/lib/omnizip/formats/rar/models/rar_entry.rb +65 -0
  370. data/lib/omnizip/formats/rar/models/rar_volume.rb +56 -0
  371. data/lib/omnizip/formats/rar/models.rb +14 -0
  372. data/lib/omnizip/formats/rar/parity_handler.rb +299 -0
  373. data/lib/omnizip/formats/rar/rar5/compression/lzma.rb +200 -0
  374. data/lib/omnizip/formats/rar/rar5/compression/lzss.rb +584 -0
  375. data/lib/omnizip/formats/rar/rar5/compression/store.rb +60 -0
  376. data/lib/omnizip/formats/rar/rar5/crc32.rb +39 -0
  377. data/lib/omnizip/formats/rar/rar5/encryption/aes256_cbc.rb +96 -0
  378. data/lib/omnizip/formats/rar/rar5/encryption/encryption_header.rb +114 -0
  379. data/lib/omnizip/formats/rar/rar5/encryption/encryption_manager.rb +162 -0
  380. data/lib/omnizip/formats/rar/rar5/encryption/key_derivation.rb +97 -0
  381. data/lib/omnizip/formats/rar/rar5/header.rb +208 -0
  382. data/lib/omnizip/formats/rar/rar5/models/encryption_options.rb +74 -0
  383. data/lib/omnizip/formats/rar/rar5/models/recovery_options.rb +63 -0
  384. data/lib/omnizip/formats/rar/rar5/models/solid_options.rb +63 -0
  385. data/lib/omnizip/formats/rar/rar5/models/volume_options.rb +74 -0
  386. data/lib/omnizip/formats/rar/rar5/multi_volume/ARCHITECTURE.md +290 -0
  387. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_manager.rb +260 -0
  388. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_splitter.rb +155 -0
  389. data/lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb +176 -0
  390. data/lib/omnizip/formats/rar/rar5/solid/solid_encoder.rb +108 -0
  391. data/lib/omnizip/formats/rar/rar5/solid/solid_manager.rb +139 -0
  392. data/lib/omnizip/formats/rar/rar5/solid/solid_stream.rb +121 -0
  393. data/lib/omnizip/formats/rar/rar5/vint.rb +53 -0
  394. data/lib/omnizip/formats/rar/rar5/writer.rb +540 -0
  395. data/lib/omnizip/formats/rar/rar_format_base.rb +239 -0
  396. data/lib/omnizip/formats/rar/reader.rb +377 -0
  397. data/lib/omnizip/formats/rar/recovery_record.rb +245 -0
  398. data/lib/omnizip/formats/rar/volume_manager.rb +166 -0
  399. data/lib/omnizip/formats/rar/writer.rb +437 -0
  400. data/lib/omnizip/formats/rar.rb +193 -0
  401. data/lib/omnizip/formats/rar3/compressor.rb +71 -0
  402. data/lib/omnizip/formats/rar3/decompressor.rb +64 -0
  403. data/lib/omnizip/formats/rar3/reader.rb +107 -0
  404. data/lib/omnizip/formats/rar3/writer.rb +220 -0
  405. data/lib/omnizip/formats/rar3.rb +15 -0
  406. data/lib/omnizip/formats/rar5/compressor.rb +71 -0
  407. data/lib/omnizip/formats/rar5/decompressor.rb +64 -0
  408. data/lib/omnizip/formats/rar5/reader.rb +130 -0
  409. data/lib/omnizip/formats/rar5/writer.rb +65 -0
  410. data/lib/omnizip/formats/rar5.rb +15 -0
  411. data/lib/omnizip/formats/rpm/constants.rb +58 -0
  412. data/lib/omnizip/formats/rpm/entry.rb +106 -0
  413. data/lib/omnizip/formats/rpm/header.rb +106 -0
  414. data/lib/omnizip/formats/rpm/lead.rb +132 -0
  415. data/lib/omnizip/formats/rpm/tag.rb +228 -0
  416. data/lib/omnizip/formats/rpm/writer.rb +652 -0
  417. data/lib/omnizip/formats/rpm.rb +458 -0
  418. data/lib/omnizip/formats/seven_zip/bcj2_stream_decompressor.rb +274 -0
  419. data/lib/omnizip/formats/seven_zip/coder_chain.rb +169 -0
  420. data/lib/omnizip/formats/seven_zip/constants.rb +126 -0
  421. data/lib/omnizip/formats/seven_zip/encoded_header.rb +110 -0
  422. data/lib/omnizip/formats/seven_zip/encrypted_header.rb +139 -0
  423. data/lib/omnizip/formats/seven_zip/file_collector.rb +143 -0
  424. data/lib/omnizip/formats/seven_zip/header.rb +102 -0
  425. data/lib/omnizip/formats/seven_zip/header_encryptor.rb +132 -0
  426. data/lib/omnizip/formats/seven_zip/header_writer.rb +425 -0
  427. data/lib/omnizip/formats/seven_zip/models/coder_info.rb +30 -0
  428. data/lib/omnizip/formats/seven_zip/models/file_entry.rb +65 -0
  429. data/lib/omnizip/formats/seven_zip/models/folder.rb +67 -0
  430. data/lib/omnizip/formats/seven_zip/models/stream_info.rb +42 -0
  431. data/lib/omnizip/formats/seven_zip/models.rb +20 -0
  432. data/lib/omnizip/formats/seven_zip/parser.rb +671 -0
  433. data/lib/omnizip/formats/seven_zip/reader.rb +626 -0
  434. data/lib/omnizip/formats/seven_zip/split_archive_reader.rb +611 -0
  435. data/lib/omnizip/formats/seven_zip/split_archive_writer.rb +308 -0
  436. data/lib/omnizip/formats/seven_zip/stream_compressor.rb +151 -0
  437. data/lib/omnizip/formats/seven_zip/stream_decompressor.rb +166 -0
  438. data/lib/omnizip/formats/seven_zip/writer.rb +801 -0
  439. data/lib/omnizip/formats/seven_zip.rb +179 -0
  440. data/lib/omnizip/formats/tar/constants.rb +73 -0
  441. data/lib/omnizip/formats/tar/entry.rb +98 -0
  442. data/lib/omnizip/formats/tar/header.rb +206 -0
  443. data/lib/omnizip/formats/tar/reader.rb +119 -0
  444. data/lib/omnizip/formats/tar/writer.rb +212 -0
  445. data/lib/omnizip/formats/tar.rb +74 -0
  446. data/lib/omnizip/formats/xar/constants.rb +119 -0
  447. data/lib/omnizip/formats/xar/entry.rb +268 -0
  448. data/lib/omnizip/formats/xar/header.rb +223 -0
  449. data/lib/omnizip/formats/xar/reader.rb +400 -0
  450. data/lib/omnizip/formats/xar/toc.rb +570 -0
  451. data/lib/omnizip/formats/xar/writer.rb +461 -0
  452. data/lib/omnizip/formats/xar.rb +145 -0
  453. data/lib/omnizip/formats/xz/reader.rb +121 -0
  454. data/lib/omnizip/formats/xz/writer.rb +416 -0
  455. data/lib/omnizip/formats/xz.rb +210 -0
  456. data/lib/omnizip/formats/xz_const.rb +49 -0
  457. data/lib/omnizip/formats/xz_impl/block_decoder.rb +761 -0
  458. data/lib/omnizip/formats/xz_impl/block_encoder.rb +304 -0
  459. data/lib/omnizip/formats/xz_impl/block_header.rb +210 -0
  460. data/lib/omnizip/formats/xz_impl/block_header_parser.rb +182 -0
  461. data/lib/omnizip/formats/xz_impl/index_decoder.rb +174 -0
  462. data/lib/omnizip/formats/xz_impl/index_encoder.rb +120 -0
  463. data/lib/omnizip/formats/xz_impl/stream_decoder.rb +470 -0
  464. data/lib/omnizip/formats/xz_impl/stream_encoder.rb +95 -0
  465. data/lib/omnizip/formats/xz_impl/stream_footer.rb +79 -0
  466. data/lib/omnizip/formats/xz_impl/stream_footer_parser.rb +115 -0
  467. data/lib/omnizip/formats/xz_impl/stream_header.rb +53 -0
  468. data/lib/omnizip/formats/xz_impl/stream_header_parser.rb +106 -0
  469. data/lib/omnizip/formats/xz_impl/vli.rb +128 -0
  470. data/lib/omnizip/formats/xz_impl.rb +52 -0
  471. data/lib/omnizip/formats/zip/central_directory_header.rb +223 -0
  472. data/lib/omnizip/formats/zip/constants.rb +69 -0
  473. data/lib/omnizip/formats/zip/end_of_central_directory.rb +132 -0
  474. data/lib/omnizip/formats/zip/local_file_header.rb +136 -0
  475. data/lib/omnizip/formats/zip/reader.rb +376 -0
  476. data/lib/omnizip/formats/zip/unix_extra_field.rb +153 -0
  477. data/lib/omnizip/formats/zip/writer.rb +489 -0
  478. data/lib/omnizip/formats/zip/zip64_end_of_central_directory.rb +102 -0
  479. data/lib/omnizip/formats/zip/zip64_end_of_central_directory_locator.rb +64 -0
  480. data/lib/omnizip/formats/zip/zip64_extra_field.rb +112 -0
  481. data/lib/omnizip/formats/zip.rb +50 -0
  482. data/lib/omnizip/formats.rb +29 -0
  483. data/lib/omnizip/implementations/base/lzma2_decoder_base.rb +75 -0
  484. data/lib/omnizip/implementations/base/lzma2_encoder_base.rb +128 -0
  485. data/lib/omnizip/implementations/base/lzma_decoder_base.rb +83 -0
  486. data/lib/omnizip/implementations/base/lzma_encoder_base.rb +108 -0
  487. data/lib/omnizip/implementations/base/state_machine_base.rb +182 -0
  488. data/lib/omnizip/implementations/base.rb +19 -0
  489. data/lib/omnizip/implementations/rust/archive.rb +93 -0
  490. data/lib/omnizip/implementations/rust/library.rb +221 -0
  491. data/lib/omnizip/implementations/rust.rb +26 -0
  492. data/lib/omnizip/implementations/seven_zip/lzma/decoder.rb +428 -0
  493. data/lib/omnizip/implementations/seven_zip/lzma/encoder.rb +456 -0
  494. data/lib/omnizip/implementations/seven_zip/lzma/match_finder.rb +285 -0
  495. data/lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb +197 -0
  496. data/lib/omnizip/implementations/seven_zip/lzma/range_encoder.rb +194 -0
  497. data/lib/omnizip/implementations/seven_zip/lzma/state_machine.rb +139 -0
  498. data/lib/omnizip/implementations/seven_zip/lzma.rb +21 -0
  499. data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +56 -0
  500. data/lib/omnizip/implementations/seven_zip/lzma2.rb +12 -0
  501. data/lib/omnizip/implementations/seven_zip.rb +11 -0
  502. data/lib/omnizip/implementations/xz_utils/lzma2/decoder.rb +547 -0
  503. data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +748 -0
  504. data/lib/omnizip/implementations/xz_utils/lzma2.rb +13 -0
  505. data/lib/omnizip/implementations/xz_utils.rb +10 -0
  506. data/lib/omnizip/implementations.rb +25 -0
  507. data/lib/omnizip/io/buffered_input.rb +147 -0
  508. data/lib/omnizip/io/buffered_output.rb +106 -0
  509. data/lib/omnizip/io/source.rb +143 -0
  510. data/lib/omnizip/io/stream_manager.rb +117 -0
  511. data/lib/omnizip/io.rb +15 -0
  512. data/lib/omnizip/link_handler/hard_link.rb +79 -0
  513. data/lib/omnizip/link_handler/symbolic_link.rb +74 -0
  514. data/lib/omnizip/link_handler.rb +129 -0
  515. data/lib/omnizip/metadata/archive_metadata.rb +114 -0
  516. data/lib/omnizip/metadata/entry_metadata.rb +153 -0
  517. data/lib/omnizip/metadata/metadata_editor.rb +169 -0
  518. data/lib/omnizip/metadata/metadata_registry.rb +71 -0
  519. data/lib/omnizip/metadata/metadata_validator.rb +101 -0
  520. data/lib/omnizip/metadata.rb +58 -0
  521. data/lib/omnizip/models/.keep +0 -0
  522. data/lib/omnizip/models/algorithm_metadata.rb +41 -0
  523. data/lib/omnizip/models/attribute_apply.rb +40 -0
  524. data/lib/omnizip/models/compression_options.rb +53 -0
  525. data/lib/omnizip/models/conversion_options.rb +79 -0
  526. data/lib/omnizip/models/conversion_result.rb +141 -0
  527. data/lib/omnizip/models/eta_result.rb +45 -0
  528. data/lib/omnizip/models/extraction_rule.rb +115 -0
  529. data/lib/omnizip/models/filter_chain.rb +142 -0
  530. data/lib/omnizip/models/filter_config.rb +148 -0
  531. data/lib/omnizip/models/match_result.rb +141 -0
  532. data/lib/omnizip/models/optimization_suggestion.rb +95 -0
  533. data/lib/omnizip/models/parallel_options.rb +116 -0
  534. data/lib/omnizip/models/performance_result.rb +85 -0
  535. data/lib/omnizip/models/profile_report.rb +116 -0
  536. data/lib/omnizip/models/progress_options.rb +39 -0
  537. data/lib/omnizip/models/split_options.rb +116 -0
  538. data/lib/omnizip/optimization_registry.rb +45 -0
  539. data/lib/omnizip/parallel/engine.rb +52 -0
  540. data/lib/omnizip/parallel/job_queue.rb +209 -0
  541. data/lib/omnizip/parallel/job_scheduler.rb +225 -0
  542. data/lib/omnizip/parallel/parallel_compressor.rb +326 -0
  543. data/lib/omnizip/parallel/parallel_extractor.rb +238 -0
  544. data/lib/omnizip/parallel/thread_pool.rb +60 -0
  545. data/lib/omnizip/parallel/worker_pool.rb +227 -0
  546. data/lib/omnizip/parallel.rb +156 -0
  547. data/lib/omnizip/parity/chunked_block_processor.rb +194 -0
  548. data/lib/omnizip/parity/galois16.rb +145 -0
  549. data/lib/omnizip/parity/models/creator_packet.rb +71 -0
  550. data/lib/omnizip/parity/models/file_description_packet.rb +131 -0
  551. data/lib/omnizip/parity/models/ifsc_packet.rb +111 -0
  552. data/lib/omnizip/parity/models/main_packet.rb +126 -0
  553. data/lib/omnizip/parity/models/packet.rb +156 -0
  554. data/lib/omnizip/parity/models/packet_registry.rb +102 -0
  555. data/lib/omnizip/parity/models/recovery_slice_packet.rb +76 -0
  556. data/lib/omnizip/parity/models.rb +27 -0
  557. data/lib/omnizip/parity/par2_creator.rb +496 -0
  558. data/lib/omnizip/parity/par2_repairer.rb +409 -0
  559. data/lib/omnizip/parity/par2_verifier.rb +373 -0
  560. data/lib/omnizip/parity/par2cmdline_algorithm.rb +108 -0
  561. data/lib/omnizip/parity/par2cmdline_coefficients.rb +78 -0
  562. data/lib/omnizip/parity/reed_solomon_decoder.rb +263 -0
  563. data/lib/omnizip/parity/reed_solomon_encoder.rb +108 -0
  564. data/lib/omnizip/parity/reed_solomon_matrix.rb +339 -0
  565. data/lib/omnizip/parity.rb +207 -0
  566. data/lib/omnizip/password/encryption_registry.rb +26 -0
  567. data/lib/omnizip/password/encryption_strategy.rb +96 -0
  568. data/lib/omnizip/password/password_validator.rb +129 -0
  569. data/lib/omnizip/password/winzip_aes_strategy.rb +190 -0
  570. data/lib/omnizip/password/zip_crypto_strategy.rb +135 -0
  571. data/lib/omnizip/password.rb +88 -0
  572. data/lib/omnizip/pipe/stream_compressor.rb +124 -0
  573. data/lib/omnizip/pipe/stream_decompressor.rb +173 -0
  574. data/lib/omnizip/pipe.rb +120 -0
  575. data/lib/omnizip/platform/ntfs_streams.rb +200 -0
  576. data/lib/omnizip/platform.rb +189 -0
  577. data/lib/omnizip/profile/archive_profile.rb +36 -0
  578. data/lib/omnizip/profile/balanced_profile.rb +31 -0
  579. data/lib/omnizip/profile/binary_profile.rb +33 -0
  580. data/lib/omnizip/profile/compression_profile.rb +157 -0
  581. data/lib/omnizip/profile/custom_profile.rb +155 -0
  582. data/lib/omnizip/profile/fast_profile.rb +31 -0
  583. data/lib/omnizip/profile/maximum_profile.rb +31 -0
  584. data/lib/omnizip/profile/profile_detector.rb +108 -0
  585. data/lib/omnizip/profile/profile_registry.rb +160 -0
  586. data/lib/omnizip/profile/text_profile.rb +33 -0
  587. data/lib/omnizip/profile.rb +261 -0
  588. data/lib/omnizip/profiler/memory_profiler.rb +66 -0
  589. data/lib/omnizip/profiler/method_profiler.rb +49 -0
  590. data/lib/omnizip/profiler/report_generator.rb +158 -0
  591. data/lib/omnizip/profiler.rb +192 -0
  592. data/lib/omnizip/progress/callback_reporter.rb +34 -0
  593. data/lib/omnizip/progress/console_reporter.rb +59 -0
  594. data/lib/omnizip/progress/log_reporter.rb +89 -0
  595. data/lib/omnizip/progress/operation_progress.rb +118 -0
  596. data/lib/omnizip/progress/progress_bar.rb +156 -0
  597. data/lib/omnizip/progress/progress_reporter.rb +40 -0
  598. data/lib/omnizip/progress/progress_tracker.rb +215 -0
  599. data/lib/omnizip/progress/silent_reporter.rb +22 -0
  600. data/lib/omnizip/progress.rb +131 -0
  601. data/lib/omnizip/registry.rb +111 -0
  602. data/lib/omnizip/rubyzip_compat.rb +61 -0
  603. data/lib/omnizip/temp/safe_extract.rb +124 -0
  604. data/lib/omnizip/temp/temp_file.rb +123 -0
  605. data/lib/omnizip/temp/temp_file_pool.rb +109 -0
  606. data/lib/omnizip/temp.rb +184 -0
  607. data/lib/omnizip/version.rb +5 -0
  608. data/lib/omnizip/zip/entry.rb +160 -0
  609. data/lib/omnizip/zip/file.rb +485 -0
  610. data/lib/omnizip/zip/input_stream.rb +270 -0
  611. data/lib/omnizip/zip/output_stream.rb +320 -0
  612. data/lib/omnizip/zip.rb +23 -0
  613. data/lib/omnizip.rb +157 -0
  614. data/lib/tasks/msi_test_files.rake +66 -0
  615. data/lib/tasks/platform_gems.rake +147 -0
  616. data/lib/tasks/rust_backend.rake +48 -0
  617. data/readme-docs/advanced-features.adoc +514 -0
  618. data/readme-docs/api-usage.adoc +445 -0
  619. data/readme-docs/architecture.adoc +450 -0
  620. data/readme-docs/archive-formats.adoc +479 -0
  621. data/readme-docs/cli-usage.adoc +222 -0
  622. data/readme-docs/compression-algorithms.adoc +446 -0
  623. data/readme-docs/compression-profiles.adoc +247 -0
  624. data/readme-docs/encryption-checksums.adoc +328 -0
  625. data/readme-docs/format-converter.adoc +316 -0
  626. data/readme-docs/installation.adoc +228 -0
  627. data/readme-docs/par2-archives.adoc +608 -0
  628. data/readme-docs/performance-profiler.adoc +389 -0
  629. data/readme-docs/preprocessing-filters.adoc +280 -0
  630. data/vendor/libomnizip_ffi.so +0 -0
  631. data/xz-file-format-1.2.1.txt +1174 -0
  632. metadata +768 -0
@@ -0,0 +1,308 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Formats
5
+ module SevenZip
6
+ # Split archive writer for .7z format
7
+ # Creates multi-volume archives with size limits
8
+ class SplitArchiveWriter
9
+ include Omnizip::Formats::SevenZip::Constants
10
+
11
+ attr_reader :base_path, :options, :split_options, :entries, :volumes
12
+
13
+ # Volume information
14
+ class VolumeInfo
15
+ attr_accessor :path, :size, :start_offset, :end_offset
16
+
17
+ def initialize(path, start_offset = 0)
18
+ @path = path
19
+ @size = 0
20
+ @start_offset = start_offset
21
+ @end_offset = start_offset
22
+ end
23
+ end
24
+
25
+ # Initialize writer
26
+ #
27
+ # @param base_path [String] Base path (e.g., "backup.7z.001")
28
+ # @param options [Hash] Compression options
29
+ # @param split_options [Models::SplitOptions] Split configuration
30
+ def initialize(base_path, options = {}, split_options = nil)
31
+ @base_path = base_path
32
+ @options = {
33
+ algorithm: :lzma2,
34
+ level: 5,
35
+ solid: true,
36
+ filters: [],
37
+ }.merge(options)
38
+ @split_options = split_options || Models::SplitOptions.new
39
+ @split_options.validate!
40
+ @collector = FileCollector.new
41
+ @entries = []
42
+ @volumes = []
43
+ @current_volume = nil
44
+ @current_volume_number = 1
45
+ @global_offset = 0
46
+ end
47
+
48
+ # Add file to archive
49
+ #
50
+ # @param file_path [String] Path to file
51
+ # @param archive_path [String, nil] Path in archive
52
+ def add_file(file_path, archive_path = nil)
53
+ @collector.add_path(file_path, archive_path: archive_path,
54
+ recursive: false)
55
+ end
56
+
57
+ # Add directory to archive
58
+ #
59
+ # @param dir_path [String] Path to directory
60
+ # @param recursive [Boolean] Add contents recursively
61
+ def add_directory(dir_path, recursive: true)
62
+ @collector.add_path(dir_path, recursive: recursive)
63
+ end
64
+
65
+ # Add files matching glob pattern
66
+ #
67
+ # @param pattern [String] Glob pattern
68
+ def add_files(pattern)
69
+ @collector.add_glob(pattern)
70
+ end
71
+
72
+ # Write split archive
73
+ #
74
+ # @raise [RuntimeError] on write error
75
+ def write
76
+ # Collect files
77
+ @entries = @collector.collect_files
78
+
79
+ # Determine spanning strategy
80
+ if @split_options.span_strategy == Omnizip::Models::SplitOptions::STRATEGY_BALANCED
81
+ write_balanced
82
+ else
83
+ write_first_fit
84
+ end
85
+ end
86
+
87
+ private
88
+
89
+ # Write using first-fit strategy (default)
90
+ def write_first_fit
91
+ # Compress all files first
92
+ compressed_result = compress_files
93
+
94
+ # Calculate total size needed
95
+ compressed_result[:data].bytesize
96
+ header_data = build_next_header(compressed_result)
97
+ header_data.bytesize
98
+
99
+ # Create volumes and write data
100
+ start_first_volume
101
+ write_packed_data(compressed_result[:data])
102
+
103
+ # Write header at the end of last volume
104
+ header_offset = @global_offset - START_HEADER_SIZE
105
+ write_data(header_data)
106
+
107
+ # Write start header to first volume (this closes volumes)
108
+ write_start_header_to_first_volume(header_data, header_offset)
109
+ end
110
+
111
+ # Write using balanced strategy
112
+ # Pre-calculates optimal file distribution
113
+ def write_balanced
114
+ # For now, use first-fit strategy
115
+ # Full balanced implementation would require:
116
+ # 1. Calculate individual file sizes
117
+ # 2. Use bin-packing algorithm
118
+ # 3. Distribute files optimally
119
+ write_first_fit
120
+ end
121
+
122
+ # Compress all files
123
+ #
124
+ # @return [Hash] Compression results
125
+ def compress_files
126
+ compressor = StreamCompressor.new(
127
+ algorithm: @options[:algorithm],
128
+ level: @options[:level],
129
+ filters: @options[:filters],
130
+ )
131
+
132
+ files_with_data = @entries.select(&:has_stream?)
133
+
134
+ if @options[:solid]
135
+ # Solid: compress all files into one stream
136
+ result = compressor.compress_files(files_with_data)
137
+ files_with_data.each_with_index do |entry, i|
138
+ entry.crc = result[:crcs][i]
139
+ entry.size = result[:unpack_sizes][i]
140
+ end
141
+
142
+ {
143
+ data: result[:packed_data],
144
+ folders: [{
145
+ method_id: compressor.method_id,
146
+ properties: compressor.properties,
147
+ unpack_size: result[:unpack_size],
148
+ }],
149
+ pack_sizes: [result[:packed_size]],
150
+ unpack_sizes: result[:unpack_sizes],
151
+ digests: result[:crcs],
152
+ }
153
+ else
154
+ # Non-solid: compress each file separately
155
+ packed_data = String.new(encoding: "BINARY")
156
+ folders = []
157
+ pack_sizes = []
158
+ unpack_sizes = []
159
+ digests = []
160
+
161
+ files_with_data.each do |entry|
162
+ data = File.binread(entry.source_path)
163
+ compressed = compressor.compress(data)
164
+
165
+ packed_data << compressed
166
+ pack_sizes << compressed.bytesize
167
+ unpack_sizes << data.bytesize
168
+
169
+ # Calculate CRC
170
+ crc = Omnizip::Checksums::Crc32.new
171
+ crc.update(data)
172
+ entry.crc = crc.value
173
+ digests << crc.value
174
+
175
+ folders << {
176
+ method_id: compressor.method_id,
177
+ properties: compressor.properties,
178
+ unpack_size: data.bytesize,
179
+ }
180
+ end
181
+
182
+ {
183
+ data: packed_data,
184
+ folders: folders,
185
+ pack_sizes: pack_sizes,
186
+ unpack_sizes: unpack_sizes,
187
+ digests: digests,
188
+ }
189
+ end
190
+ end
191
+
192
+ # Build next header metadata
193
+ #
194
+ # @param compressed_result [Hash] Compression results
195
+ # @return [String] Encoded next header
196
+ def build_next_header(compressed_result)
197
+ header_writer = HeaderWriter.new
198
+
199
+ header_options = {
200
+ streams: {
201
+ pack_pos: 0,
202
+ pack_sizes: compressed_result[:pack_sizes],
203
+ pack_crcs: [],
204
+ folders: compressed_result[:folders],
205
+ unpack_sizes: compressed_result[:unpack_sizes],
206
+ digests: compressed_result[:digests],
207
+ },
208
+ entries: @entries,
209
+ }
210
+
211
+ header_writer.write_next_header(header_options)
212
+ end
213
+
214
+ # Start first volume
215
+ def start_first_volume
216
+ volume_path = @split_options.volume_filename(@base_path, 1)
217
+ @current_volume = File.open(volume_path, "wb")
218
+ @volumes << VolumeInfo.new(volume_path, 0)
219
+
220
+ # Reserve space for start header (will be written at end)
221
+ @current_volume.write("\0" * START_HEADER_SIZE)
222
+ @global_offset = START_HEADER_SIZE
223
+ @volumes.last.size = START_HEADER_SIZE
224
+ @volumes.last.end_offset = START_HEADER_SIZE
225
+ end
226
+
227
+ # Write packed data across volumes
228
+ #
229
+ # @param data [String] Data to write
230
+ def write_packed_data(data)
231
+ offset = 0
232
+ remaining = data.bytesize
233
+
234
+ while remaining.positive?
235
+ available = @split_options.volume_size - @volumes.last.size
236
+
237
+ # If current volume is full, start a new one
238
+ if available <= 0
239
+ close_current_volume
240
+ start_continuation_volume
241
+ available = @split_options.volume_size
242
+ end
243
+
244
+ chunk_size = [available, remaining].min
245
+
246
+ if chunk_size.positive?
247
+ chunk = data[offset, chunk_size]
248
+ @current_volume.write(chunk)
249
+ @volumes.last.size += chunk_size
250
+ @volumes.last.end_offset += chunk_size
251
+ @global_offset += chunk_size
252
+ offset += chunk_size
253
+ remaining -= chunk_size
254
+ end
255
+ end
256
+ end
257
+
258
+ # Write data (may span volumes)
259
+ #
260
+ # @param data [String] Data to write
261
+ def write_data(data)
262
+ write_packed_data(data)
263
+ end
264
+
265
+ # Start continuation volume
266
+ def start_continuation_volume
267
+ @current_volume_number += 1
268
+ volume_path = @split_options.volume_filename(@base_path,
269
+ @current_volume_number)
270
+ @current_volume = File.open(volume_path, "wb")
271
+ @volumes << VolumeInfo.new(volume_path, @global_offset)
272
+ end
273
+
274
+ # Write start header to first volume
275
+ #
276
+ # @param header_data [String] Header data
277
+ # @param header_offset [Integer] Offset to header
278
+ def write_start_header_to_first_volume(header_data, header_offset)
279
+ # Close current volume first to ensure all data is flushed
280
+ close_current_volume
281
+
282
+ header_writer = HeaderWriter.new
283
+ start_header = header_writer.write_start_header(
284
+ header_data,
285
+ header_offset,
286
+ )
287
+
288
+ # Open first volume and write start header
289
+ first_volume_path = @volumes.first.path
290
+ File.open(first_volume_path, "r+b") do |io|
291
+ io.seek(0)
292
+ io.write(start_header)
293
+ io.flush
294
+ end
295
+ end
296
+
297
+ # Close current volume
298
+ def close_current_volume
299
+ return unless @current_volume
300
+
301
+ @current_volume.flush
302
+ @current_volume.close
303
+ @current_volume = nil
304
+ end
305
+ end
306
+ end
307
+ end
308
+ end
@@ -0,0 +1,151 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "stringio"
4
+
5
+ module Omnizip
6
+ module Formats
7
+ module SevenZip
8
+ # Compresses data streams using coder chains
9
+ # Opposite of StreamDecompressor - applies compression algorithms
10
+ class StreamCompressor
11
+ attr_reader :algorithm, :level, :filters
12
+
13
+ # Initialize compressor
14
+ #
15
+ # @param algorithm [Symbol] Compression algorithm
16
+ # @param level [Integer] Compression level (1-9)
17
+ # @param filters [Array<Symbol>] Filter chain
18
+ def initialize(algorithm: :lzma2, level: 5, filters: [])
19
+ @algorithm = algorithm
20
+ @level = level
21
+ @filters = Array(filters)
22
+ end
23
+
24
+ # Compress data
25
+ #
26
+ # @param data [String] Uncompressed data
27
+ # @return [String] Compressed data
28
+ def compress(data)
29
+ result = data
30
+
31
+ # Apply filters first
32
+ @filters.each do |filter_sym|
33
+ filter_class = FilterRegistry.get(filter_sym)
34
+ next unless filter_class
35
+
36
+ filter = filter_class.new
37
+ input_io = StringIO.new(result)
38
+ output_io = StringIO.new
39
+ output_io.set_encoding("BINARY")
40
+ filter.encode(input_io, output_io)
41
+ result = output_io.string
42
+ end
43
+
44
+ # Apply compression algorithm
45
+ if @algorithm && @algorithm != :copy
46
+ algo_class = Omnizip::AlgorithmRegistry.get(@algorithm)
47
+ raise Omnizip::AlgorithmNotFoundError, "Algorithm not found: #{@algorithm}" unless algo_class
48
+
49
+ encoder = algo_class.new
50
+ input_io = StringIO.new(result)
51
+ output_io = StringIO.new
52
+ output_io.set_encoding("BINARY")
53
+
54
+ # For 7-Zip format, use raw_mode (no property byte in compressed data)
55
+ # The properties are encoded in the 7-Zip header instead
56
+ encoder.compress(input_io, output_io,
57
+ { raw_mode: true, standalone: false })
58
+ result = output_io.string
59
+ end
60
+
61
+ result
62
+ end
63
+
64
+ # Compress multiple files into single stream (solid compression)
65
+ #
66
+ # @param file_entries [Array<Models::FileEntry>] Files to compress
67
+ # @return [Hash] Compression result with packed/unpacked sizes
68
+ def compress_files(file_entries)
69
+ # Concatenate all file data
70
+ combined_data = String.new(encoding: "BINARY")
71
+ unpack_sizes = []
72
+ crcs = []
73
+
74
+ file_entries.each do |entry|
75
+ next unless entry.has_stream? && entry.source_path
76
+
77
+ data = File.binread(entry.source_path)
78
+ combined_data << data
79
+ unpack_sizes << data.bytesize
80
+
81
+ # Calculate CRC
82
+ crc = Omnizip::Checksums::Crc32.new
83
+ crc.update(data)
84
+ crcs << crc.value
85
+ end
86
+
87
+ # Compress combined data
88
+ packed_data = compress(combined_data)
89
+
90
+ {
91
+ packed_data: packed_data,
92
+ packed_size: packed_data.bytesize,
93
+ unpack_size: combined_data.bytesize,
94
+ unpack_sizes: unpack_sizes,
95
+ crcs: crcs,
96
+ }
97
+ end
98
+
99
+ # Get method ID for this compression algorithm
100
+ #
101
+ # @return [Integer] Method ID
102
+ def method_id
103
+ case @algorithm
104
+ when :copy then Constants::MethodId::COPY
105
+ when :lzma then Constants::MethodId::LZMA
106
+ when :lzma2 then Constants::MethodId::LZMA2
107
+ when :ppmd, :ppmd7 then Constants::MethodId::PPMD
108
+ when :bzip2 then Constants::MethodId::BZIP2
109
+ else Constants::MethodId::LZMA2
110
+ end
111
+ end
112
+
113
+ # Get filter IDs for filter chain
114
+ #
115
+ # @return [Array<Integer>] Filter IDs
116
+ def filter_ids
117
+ @filters.filter_map do |filter_sym|
118
+ case filter_sym
119
+ when :bcj_x86 then Constants::FilterId::BCJ_X86
120
+ when :delta then Constants::FilterId::DELTA
121
+ end
122
+ end
123
+ end
124
+
125
+ # Get properties for compression algorithm
126
+ #
127
+ # @return [String, nil] Binary properties
128
+ def properties
129
+ return nil if @algorithm == :copy || @algorithm.nil?
130
+
131
+ case @algorithm
132
+ when :lzma2
133
+ # LZMA2 properties: dictionary size encoded
134
+ dict_size = 1 << (15 + @level)
135
+ prop = 0
136
+ prop += 1 while dict_size > (2 << prop)
137
+ [prop].pack("C")
138
+ when :lzma
139
+ # LZMA properties: lc, lp, pb, dict_size
140
+ lc = 3
141
+ lp = 0
142
+ pb = 2
143
+ dict_size = 1 << (15 + @level)
144
+ [lc + (lp * 9) + (pb * 9 * 5)].pack("C") +
145
+ [dict_size].pack("V")
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,166 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "stringio"
4
+
5
+ module Omnizip
6
+ module Formats
7
+ module SevenZip
8
+ # Decompresses .7z streams using coder chains
9
+ # Handles packed stream extraction and CRC validation
10
+ class StreamDecompressor
11
+ attr_reader :archive_io, :folder, :chain_config
12
+
13
+ # Initialize decompressor
14
+ #
15
+ # @param archive_io [IO] Archive file handle
16
+ # @param folder [Models::Folder] Folder specification
17
+ # @param pack_pos [Integer] Position of packed data
18
+ # @param pack_size [Integer] Size of packed data
19
+ # @param header [Header, nil] Optional header for split archive handling
20
+ def initialize(archive_io, folder, pack_pos, pack_size, header = nil)
21
+ @archive_io = archive_io
22
+ @folder = folder
23
+ @pack_pos = pack_pos
24
+ @pack_size = pack_size
25
+ @header = header
26
+ @chain_config = CoderChain.build_from_folder(folder)
27
+ end
28
+
29
+ # Decompress stream to output
30
+ #
31
+ # @param size [Integer] Expected uncompressed size
32
+ # @return [String] Decompressed data
33
+ # @raise [RuntimeError] on decompression error
34
+ def decompress(size)
35
+ # Seek to packed data
36
+ @archive_io.seek(@pack_pos)
37
+
38
+ # For multi-volume archives, pack_size from stream_info may be incomplete.
39
+ # For solid archives spanning volumes, the actual compressed data extends
40
+ # from pack_pos to where the next header starts.
41
+ if @archive_io.is_a?(SplitArchiveReader::MultiVolumeIO) && @header
42
+ # next_header_offset is relative to start_pos_after_header
43
+ # Actual packed data size is from pack_pos to next header position
44
+ next_header_position = @header.start_pos_after_header + @header.next_header_offset
45
+ actual_pack_size = next_header_position - @pack_pos
46
+ packed_data = @archive_io.read(actual_pack_size)
47
+ else
48
+ # Regular single-file archive: use pack_size from stream info
49
+ packed_data = @archive_io.read(@pack_size)
50
+ end
51
+
52
+ return packed_data if @chain_config.nil? # No compression
53
+
54
+ # Get algorithm
55
+ algo_sym = @chain_config[:algorithm]
56
+ return packed_data unless algo_sym # Copy method
57
+
58
+ # Get algorithm class
59
+ algo_class = Omnizip::AlgorithmRegistry.get(algo_sym)
60
+ raise Omnizip::AlgorithmNotFoundError, "Algorithm not found: #{algo_sym}" unless algo_class
61
+
62
+ # Decompress
63
+ input_io = StringIO.new(packed_data)
64
+ output_io = StringIO.new
65
+ output_io.set_encoding("BINARY")
66
+
67
+ # Build options from coder properties for 7-Zip format
68
+ decoder_options = build_decoder_options
69
+
70
+ decoder = algo_class.new(decoder_options)
71
+ decoder.decompress(input_io, output_io, size: size)
72
+
73
+ result = output_io.string
74
+
75
+ # Apply filters if present
76
+ if @chain_config[:filters] && !@chain_config[:filters].empty?
77
+ @chain_config[:filters].reverse_each do |filter_sym|
78
+ filter_class = Omnizip::FilterRegistry.get(filter_sym)
79
+ next unless filter_class
80
+
81
+ # BCJ2 requires special handling with multiple streams
82
+ if filter_sym == :bcj2
83
+ raise Omnizip::UnsupportedFormatError, "BCJ2 archives require multi-stream decompression which is not yet implemented. " \
84
+ "Please use the 7z command-line tool for this archive."
85
+ end
86
+
87
+ filter = filter_class.new
88
+ filtered = StringIO.new
89
+ filter.reverse(StringIO.new(result), filtered)
90
+ result = filtered.string
91
+ end
92
+ end
93
+
94
+ result
95
+ end
96
+
97
+ # Decompress and verify CRC
98
+ #
99
+ # @param size [Integer] Expected uncompressed size
100
+ # @param expected_crc [Integer, nil] Expected CRC32 value
101
+ # @return [String] Decompressed data
102
+ # @raise [RuntimeError] if CRC mismatch
103
+ def decompress_and_verify(size, expected_crc = nil)
104
+ data = decompress(size)
105
+
106
+ if expected_crc
107
+ crc = Omnizip::Checksums::Crc32.new
108
+ crc.update(data)
109
+ actual_crc = crc.value
110
+
111
+ unless actual_crc == expected_crc
112
+ raise Omnizip::ChecksumError, "CRC mismatch: expected 0x#{expected_crc.to_s(16)}, " \
113
+ "got 0x#{actual_crc.to_s(16)}"
114
+ end
115
+ end
116
+
117
+ data
118
+ end
119
+
120
+ private
121
+
122
+ # Build decoder options from coder properties
123
+ #
124
+ # For 7-Zip format, coder properties contain algorithm-specific data.
125
+ # For LZMA2, it's a single byte encoding the dictionary size.
126
+ #
127
+ # @return [Hash] Decoder options
128
+ def build_decoder_options
129
+ return {} unless @chain_config
130
+
131
+ options = {}
132
+ properties = @chain_config[:properties]
133
+
134
+ if properties && !properties.empty?
135
+ algo_sym = @chain_config[:algorithm]
136
+
137
+ case algo_sym
138
+ when :lzma2
139
+ # LZMA2 properties: single byte encoding dictionary size
140
+ prop_byte = properties.getbyte(0)
141
+ dict_size = Omnizip::Algorithms::LZMA2::Properties.decode_dict_size(prop_byte)
142
+ options[:raw_mode] = true # No property byte in data stream
143
+ options[:dict_size] = dict_size
144
+ when :lzma
145
+ # LZMA properties: 5 bytes (prop byte + dict size)
146
+ # Format: 1 byte (lc/lp/pb) + 4 bytes (dict size LE)
147
+ if properties.bytesize >= 5
148
+ props_byte = properties.getbyte(0)
149
+ dict_size = properties[1, 4].unpack1("V")
150
+ # Use lzma2_mode to skip header reading - 7-Zip provides properties separately
151
+ options[:lzma2_mode] = true
152
+ options[:lc] = props_byte % 9
153
+ remainder = props_byte / 9
154
+ options[:lp] = remainder % 5
155
+ options[:pb] = remainder / 5
156
+ options[:dict_size] = dict_size
157
+ end
158
+ end
159
+ end
160
+
161
+ options
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end