omnizip 0.4.7-arm-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,236 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "zlib"
4
+ require "stringio"
5
+
6
+ module Omnizip
7
+ module Formats
8
+ # GZIP compression format
9
+ #
10
+ # GZIP is a file compression format that wraps Deflate compression
11
+ # with a 10-byte header and 8-byte footer containing CRC32 and
12
+ # uncompressed size.
13
+ #
14
+ # Format structure:
15
+ # - Header (10 bytes minimum):
16
+ # - Magic bytes: 0x1F 0x8B
17
+ # - Compression method: 0x08 (Deflate)
18
+ # - Flags
19
+ # - Modification time (4 bytes)
20
+ # - Extra flags
21
+ # - OS type
22
+ # - Compressed data (Deflate)
23
+ # - Footer (8 bytes):
24
+ # - CRC32 (4 bytes)
25
+ # - Uncompressed size (4 bytes, modulo 2^32)
26
+ module Gzip
27
+ # GZIP magic bytes
28
+ GZIP_MAGIC = [0x1F, 0x8B].pack("C*")
29
+
30
+ # Compression method (Deflate)
31
+ CM_DEFLATE = 8
32
+
33
+ # Flag bits
34
+ FTEXT = 0x01 # File is text
35
+ FHCRC = 0x02 # Header CRC present
36
+ FEXTRA = 0x04 # Extra fields present
37
+ FNAME = 0x08 # Original filename present
38
+ FCOMMENT = 0x10 # Comment present
39
+
40
+ # OS types
41
+ OS_FAT = 0 # FAT filesystem
42
+ OS_UNIX = 3 # Unix
43
+ OS_UNKNOWN = 255 # Unknown
44
+
45
+ class << self
46
+ # Compress a file with GZIP
47
+ #
48
+ # @param input_path [String] Input file path
49
+ # @param output_path [String] Output GZIP file path
50
+ # @param options [Hash] Compression options
51
+ # @option options [Integer] :level Compression level (0-9)
52
+ # @option options [String] :original_name Original filename
53
+ # @option options [Time] :mtime Modification time
54
+ def compress(input_path, output_path, options = {})
55
+ input_data = File.binread(input_path)
56
+
57
+ File.open(output_path, "wb") do |output|
58
+ original_name = options[:original_name] ||
59
+ File.basename(input_path)
60
+ compress_stream(
61
+ StringIO.new(input_data),
62
+ output,
63
+ options.merge(original_name: original_name),
64
+ )
65
+ end
66
+ end
67
+
68
+ # Decompress a GZIP file
69
+ #
70
+ # @param input_path [String] Input GZIP file path
71
+ # @param output_path [String] Output file path
72
+ def decompress(input_path, output_path)
73
+ File.open(input_path, "rb") do |input|
74
+ File.open(output_path, "wb") do |output|
75
+ decompress_stream(input, output)
76
+ end
77
+ end
78
+ end
79
+
80
+ # Compress data stream with GZIP
81
+ #
82
+ # @param input_io [IO] Input stream
83
+ # @param output_io [IO] Output stream
84
+ # @param options [Hash] Compression options
85
+ def compress_stream(input_io, output_io, options = {})
86
+ input_data = input_io.read
87
+ level = options[:level] || Zlib::DEFAULT_COMPRESSION
88
+ mtime = options[:mtime] || Time.now
89
+ original_name = options[:original_name]
90
+
91
+ # Write GZIP header
92
+ write_header(output_io, mtime, original_name)
93
+
94
+ # RFC 1952 member: header + RAW deflate + CRC32/ISIZE footer.
95
+ # The old implementation layered zlib's own GZIP wrapper
96
+ # under this header (a second 1F 8B magic) — the gem's
97
+ # reader tolerated it, but every standard gzip tool
98
+ # rejected the output. Raw-window mode emits bare DEFLATE.
99
+ deflate = Zlib::Deflate.new(level, -Zlib::MAX_WBITS)
100
+ output_io.write(deflate.deflate(input_data, Zlib::FINISH))
101
+ deflate.close
102
+
103
+ # Write GZIP footer
104
+ write_footer(output_io, input_data)
105
+ end
106
+
107
+ # Decompress GZIP stream
108
+ #
109
+ # @param input_io [IO] Input stream
110
+ # @param output_io [IO] Output stream
111
+ # @return [Hash] Metadata (original_name, mtime)
112
+ def decompress_stream(input_io, output_io)
113
+ data = input_io.read
114
+
115
+ # Metadata comes from the header either way (cheap parse).
116
+ metadata = read_header(StringIO.new(data))
117
+
118
+ # The tier gets the WHOLE member (header + deflate + trailer)
119
+ # — the Rust "gzip" name decodes the container end-to-end.
120
+ decompressed = Backends.decompress("gzip", data, Backends::UNKNOWN_LENGTH) do
121
+ body = StringIO.new(data)
122
+ read_header(body) # skip past the header
123
+ # Legacy double-header members (written before the RFC
124
+ # 1952 fix) carry zlib's own 10-byte GZIP header here;
125
+ # standard members carry bare DEFLATE.
126
+ rest = body.read
127
+ rest = rest.byteslice(10..) if rest.byteslice(0, 2) == "\x1F\x8B".b
128
+ inflate = Zlib::Inflate.new(-Zlib::MAX_WBITS)
129
+ result = inflate.inflate(rest)
130
+ inflate.close
131
+ result
132
+ end
133
+
134
+ output_io.write(decompressed)
135
+
136
+ metadata
137
+ end
138
+
139
+ private
140
+
141
+ # Write GZIP header
142
+ #
143
+ # @param output [IO] Output stream
144
+ # @param mtime [Time] Modification time
145
+ # @param original_name [String, nil] Original filename
146
+ def write_header(output, mtime, original_name = nil)
147
+ flags = 0
148
+ flags |= FNAME if original_name
149
+
150
+ header = [
151
+ 0x1F, 0x8B, # Magic
152
+ CM_DEFLATE, # Compression method
153
+ flags, # Flags
154
+ mtime.to_i, # Modification time
155
+ 0, # Extra flags
156
+ OS_UNIX # OS type
157
+ ].pack("C C C C V C C")
158
+
159
+ output.write(header)
160
+
161
+ # Write original filename if present
162
+ return unless original_name
163
+
164
+ output.write(original_name)
165
+ output.write("\0")
166
+ end
167
+
168
+ # Read GZIP header
169
+ #
170
+ # @param input [IO] Input stream
171
+ # @return [Hash] Header metadata
172
+ def read_header(input)
173
+ magic = input.read(2)
174
+ unless magic == GZIP_MAGIC
175
+ raise Error, "Not a GZIP file (invalid magic bytes)"
176
+ end
177
+
178
+ cm = input.read(1).unpack1("C")
179
+ unless cm == CM_DEFLATE
180
+ raise Error, "Unsupported GZIP compression method: #{cm}"
181
+ end
182
+
183
+ flags = input.read(1).unpack1("C")
184
+ mtime = Time.at(input.read(4).unpack1("V"))
185
+ _xfl = input.read(1)
186
+ _os = input.read(1)
187
+
188
+ metadata = { mtime: mtime }
189
+
190
+ # Read extra fields if present
191
+ if flags.anybits?(FEXTRA)
192
+ xlen = input.read(2).unpack1("v")
193
+ input.read(xlen) # Skip extra data
194
+ end
195
+
196
+ # Read original filename if present
197
+ if flags.anybits?(FNAME)
198
+ name = +""
199
+ loop do
200
+ byte = input.read(1)
201
+ break if byte == "\0"
202
+
203
+ name << byte
204
+ end
205
+ metadata[:original_name] = name
206
+ end
207
+
208
+ # Read comment if present
209
+ if flags.anybits?(FCOMMENT)
210
+ loop do
211
+ byte = input.read(1)
212
+ break if byte == "\0"
213
+ end
214
+ end
215
+
216
+ # Read header CRC if present
217
+ input.read(2) if flags.anybits?(FHCRC)
218
+
219
+ metadata
220
+ end
221
+
222
+ # Write GZIP footer
223
+ #
224
+ # @param output [IO] Output stream
225
+ # @param uncompressed_data [String] Original uncompressed data
226
+ def write_footer(output, uncompressed_data)
227
+ crc32 = Zlib.crc32(uncompressed_data)
228
+ size = uncompressed_data.bytesize & 0xFFFFFFFF
229
+
230
+ footer = [crc32, size].pack("VV")
231
+ output.write(footer)
232
+ end
233
+ end
234
+ end
235
+ end
236
+ end
@@ -0,0 +1,321 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Formats
5
+ module Iso
6
+ # ISO 9660 Directory Structure Builder
7
+ #
8
+ # Builds the hierarchical directory structure for an ISO image,
9
+ # allocating sectors for directories and files.
10
+ class DirectoryBuilder
11
+ # @return [Array<Hash>] Files to add
12
+ attr_reader :files
13
+
14
+ # @return [Array<Hash>] Directories to add
15
+ attr_reader :directories
16
+
17
+ # @return [Integer] ISO level
18
+ attr_reader :level
19
+
20
+ # @return [Boolean] Rock Ridge enabled
21
+ attr_reader :rock_ridge
22
+
23
+ # Initialize directory builder
24
+ #
25
+ # @param files [Array<Hash>] Files to include
26
+ # @param directories [Array<Hash>] Directories to include
27
+ # @param options [Hash] Builder options
28
+ def initialize(files, directories, options = {})
29
+ @files = files
30
+ @directories = directories
31
+ @level = options.fetch(:level, 2)
32
+ @rock_ridge = options.fetch(:rock_ridge, false)
33
+ @current_sector = 22 # After volume descriptors and path tables
34
+ end
35
+
36
+ # Build directory structure
37
+ #
38
+ # @return [Hash] Complete directory structure with allocations
39
+ def build
40
+ # Build directory tree
41
+ tree = build_directory_tree
42
+
43
+ # Allocate sectors for directories and files
44
+ allocate_sectors(tree)
45
+
46
+ # Tree nodes are separate hashes from @files entries; copy
47
+ # the allocated file locations onto the tree so directory
48
+ # records reference the real extents (otherwise every
49
+ # record points at sector 0).
50
+ assign_file_locations(tree)
51
+
52
+ # Build path table
53
+ path_table = build_path_table(tree)
54
+
55
+ {
56
+ root: tree,
57
+ directories: flatten_directories(tree),
58
+ files: @files,
59
+ path_table: path_table,
60
+ path_table_size: path_table.bytesize,
61
+ total_sectors: @current_sector,
62
+ }
63
+ end
64
+
65
+ private
66
+
67
+ # Build directory tree from files and directories
68
+ #
69
+ # @return [Hash] Root directory node
70
+ def build_directory_tree
71
+ root = {
72
+ name: "\x00", # Root directory identifier
73
+ iso_path: "",
74
+ children: [],
75
+ directory: true,
76
+ stat: nil,
77
+ }
78
+
79
+ # Add all directories first
80
+ @directories.each do |dir_info|
81
+ add_to_tree(root, dir_info[:iso_path], dir_info)
82
+ end
83
+
84
+ # Add all files
85
+ @files.each do |file_info|
86
+ add_to_tree(root, file_info[:iso_path], file_info)
87
+ end
88
+
89
+ root
90
+ end
91
+
92
+ # Add entry to directory tree
93
+ #
94
+ # @param root [Hash] Root node
95
+ # @param path [String] Entry path
96
+ # @param info [Hash] Entry information
97
+ def add_to_tree(root, path, info)
98
+ parts = path.split("/")
99
+ current = root
100
+
101
+ # Navigate/create directory structure
102
+ parts[0...-1].each do |part|
103
+ # Ensure current node has children array (it should be a directory)
104
+ current[:children] ||= []
105
+ child = current[:children].find { |c| c[:name] == part }
106
+
107
+ unless child
108
+ child = {
109
+ name: part,
110
+ iso_path: [current[:iso_path], part].reject(&:empty?).join("/"),
111
+ children: [],
112
+ directory: true,
113
+ stat: nil,
114
+ }
115
+ current[:children] << child
116
+ end
117
+
118
+ current = child
119
+ end
120
+
121
+ # Add the actual entry
122
+ entry_name = parts.last
123
+ entry = {
124
+ name: entry_name,
125
+ iso_path: path,
126
+ children: info[:directory] ? [] : nil,
127
+ directory: info[:directory] || false,
128
+ stat: info[:stat],
129
+ source: info[:source],
130
+ size: info[:directory] ? 0 : File.size(info[:source]),
131
+ }
132
+
133
+ # Ensure current node has children array
134
+ current[:children] ||= []
135
+ current[:children] << entry
136
+ end
137
+
138
+ # Allocate sectors for all entries
139
+ #
140
+ # @param tree [Hash] Directory tree
141
+ def allocate_sectors(tree)
142
+ # Allocate for root directory
143
+ allocate_directory_sectors(tree)
144
+
145
+ # Recursively allocate for children
146
+ allocate_children_sectors(tree)
147
+
148
+ # Allocate for files
149
+ allocate_file_sectors
150
+ end
151
+
152
+ # Copy allocated file locations onto the matching tree nodes
153
+ #
154
+ # @param tree [Hash] Directory tree root
155
+ def assign_file_locations(tree)
156
+ walk = lambda do |node|
157
+ (node[:children] || []).each do |child|
158
+ if child[:directory]
159
+ walk.call(child)
160
+ else
161
+ match = @files.find { |f| f[:iso_path] == child[:iso_path] }
162
+ child[:location] = match[:location] if match
163
+ child[:size] = match[:size] if match
164
+ end
165
+ end
166
+ end
167
+ walk.call(tree)
168
+ end
169
+
170
+ # Allocate sectors for a directory
171
+ #
172
+ # @param dir_node [Hash] Directory node
173
+ def allocate_directory_sectors(dir_node)
174
+ # Calculate directory size
175
+ dir_size = calculate_directory_size(dir_node)
176
+ sectors_needed = (dir_size.to_f / Iso::SECTOR_SIZE).ceil
177
+
178
+ # Allocate location
179
+ dir_node[:location] = @current_sector
180
+ dir_node[:size] = dir_size
181
+
182
+ @current_sector += sectors_needed
183
+ end
184
+
185
+ # Calculate directory data size
186
+ #
187
+ # @param dir_node [Hash] Directory node
188
+ # @return [Integer] Size in bytes
189
+ def calculate_directory_size(dir_node)
190
+ size = 0
191
+
192
+ # Size for "." entry (34 bytes minimum)
193
+ size += 34
194
+
195
+ # Size for ".." entry
196
+ size += 34
197
+
198
+ # Size for each child entry
199
+ dir_node[:children].each do |child|
200
+ name_len = child[:name].bytesize
201
+ padding = name_len.even? ? 1 : 0
202
+ entry_size = 33 + name_len + padding
203
+
204
+ # Add Rock Ridge System Use fields if enabled
205
+ entry_size += calculate_rock_ridge_size(child) if @rock_ridge
206
+
207
+ size += entry_size
208
+ end
209
+
210
+ # Round up to sector boundary
211
+ ((size.to_f / Iso::SECTOR_SIZE).ceil * Iso::SECTOR_SIZE)
212
+ end
213
+
214
+ # Calculate Rock Ridge System Use field size
215
+ #
216
+ # @param entry [Hash] Entry information
217
+ # @return [Integer] Size in bytes
218
+ def calculate_rock_ridge_size(_entry)
219
+ # Basic Rock Ridge fields:
220
+ # - PX (POSIX attributes): 44 bytes
221
+ # - TF (timestamps): 26 bytes
222
+ # - NM (alternate name): variable
223
+ # For now, estimate 100 bytes
224
+ 100
225
+ end
226
+
227
+ # Allocate sectors for children recursively
228
+ #
229
+ # @param dir_node [Hash] Directory node
230
+ def allocate_children_sectors(dir_node)
231
+ dir_node[:children].each do |child|
232
+ next unless child[:directory]
233
+
234
+ allocate_directory_sectors(child)
235
+ allocate_children_sectors(child)
236
+ end
237
+ end
238
+
239
+ # Allocate sectors for files
240
+ def allocate_file_sectors
241
+ @files.each do |file_info|
242
+ file_size = file_info[:stat].size
243
+ sectors_needed = (file_size.to_f / Iso::SECTOR_SIZE).ceil
244
+
245
+ file_info[:location] = @current_sector
246
+ file_info[:size] = file_size
247
+
248
+ @current_sector += sectors_needed
249
+ end
250
+ end
251
+
252
+ # Build path table from directory tree
253
+ #
254
+ # @param tree [Hash] Directory tree
255
+ # @return [String] Path table data
256
+ def build_path_table(tree)
257
+ table = +""
258
+ directories = []
259
+
260
+ # Collect all directories in path table order
261
+ collect_directories_for_path_table(tree, directories)
262
+
263
+ # Build path table entries
264
+ directories.each_with_index do |dir, _idx|
265
+ name = dir[:name] == "\x00" ? "\x00" : dir[:name]
266
+ parent_idx = dir[:parent_idx] || 0
267
+
268
+ # Name length
269
+ table << [name.bytesize].pack("C")
270
+
271
+ # Extended attribute length
272
+ table << [0].pack("C")
273
+
274
+ # Location of extent
275
+ table << [dir[:location]].pack("V")
276
+
277
+ # Parent directory number (1-based)
278
+ table << [parent_idx + 1].pack("v")
279
+
280
+ # Directory name
281
+ table << name
282
+
283
+ # Pad to even length
284
+ table << "\x00" if name.bytesize.odd?
285
+ end
286
+
287
+ table
288
+ end
289
+
290
+ # Collect directories in depth-first order for path table
291
+ #
292
+ # @param node [Hash] Current node
293
+ # @param list [Array<Hash>] Output list
294
+ # @param parent_idx [Integer, nil] Parent index
295
+ def collect_directories_for_path_table(node, list, parent_idx = nil)
296
+ current_idx = list.size
297
+ node[:parent_idx] = parent_idx
298
+ list << node
299
+
300
+ node[:children].select { |c| c[:directory] }.each do |child|
301
+ collect_directories_for_path_table(child, list, current_idx)
302
+ end
303
+ end
304
+
305
+ # Flatten directory tree to array
306
+ #
307
+ # @param tree [Hash] Directory tree
308
+ # @return [Array<Hash>] Flat directory list
309
+ def flatten_directories(tree)
310
+ result = [tree]
311
+
312
+ tree[:children].select { |c| c[:directory] }.each do |child|
313
+ result.concat(flatten_directories(child))
314
+ end
315
+
316
+ result
317
+ end
318
+ end
319
+ end
320
+ end
321
+ end
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Formats
5
+ module Iso
6
+ # ISO 9660 Directory Record
7
+ # Represents a file or directory entry
8
+ class DirectoryRecord
9
+ include Omnizip::Entry
10
+
11
+ attr_accessor :full_path
12
+ attr_reader :length, :extended_attr_length, :location, :data_length, :recording_date, :flags, :file_unit_size, :interleave_gap_size, :volume_sequence_number, :name, :system_use
13
+
14
+ def entry_name = full_path || name
15
+ def entry_directory? = directory?
16
+ def entry_size = data_length
17
+ def entry_mtime = recording_date
18
+
19
+ # Set the full path for this record, used by Reader when walking
20
+ # a directory tree. Allows callers to look up records by path
21
+ # without re-joining parent names.
22
+
23
+ # Parse directory record from binary data
24
+ #
25
+ # @param data [String] Binary record data
26
+ # @param offset [Integer] Offset in data to start parsing
27
+ # @return [DirectoryRecord] Parsed record
28
+ def self.parse(data, offset = 0)
29
+ new.tap { |record| record.parse(data, offset) }
30
+ end
31
+
32
+ # Parse record data
33
+ #
34
+ # @param data [String] Binary data
35
+ # @param offset [Integer] Starting offset
36
+ def parse(data, offset = 0)
37
+ # Byte 0: Length of directory record
38
+ @length = data.getbyte(offset)
39
+ return if @length.zero? # Padding
40
+
41
+ # Byte 1: Extended attribute record length
42
+ @extended_attr_length = data.getbyte(offset + 1)
43
+
44
+ # Bytes 2-9: Location of extent (both-endian)
45
+ @location = data[offset + 2, 4].unpack1("V")
46
+
47
+ # Bytes 10-17: Data length (both-endian)
48
+ @data_length = data[offset + 10, 4].unpack1("V")
49
+
50
+ # Bytes 18-24: Recording date and time
51
+ @recording_date = parse_record_datetime(data[offset + 18, 7])
52
+
53
+ # Byte 25: File flags
54
+ @flags = data.getbyte(offset + 25)
55
+
56
+ # Byte 26: File unit size (for interleaved files)
57
+ @file_unit_size = data.getbyte(offset + 26)
58
+
59
+ # Byte 27: Interleave gap size
60
+ @interleave_gap_size = data.getbyte(offset + 27)
61
+
62
+ # Bytes 28-31: Volume sequence number (both-endian)
63
+ @volume_sequence_number = data[offset + 28, 2].unpack1("v")
64
+
65
+ # Byte 32: Length of file identifier
66
+ name_length = data.getbyte(offset + 32)
67
+
68
+ # Bytes 33+: File identifier
69
+ @name = data[offset + 33, name_length]
70
+
71
+ # Parse file identifier
72
+ parse_name
73
+
74
+ # System Use field (Rock Ridge extensions, etc.)
75
+ # Located after name and padding
76
+ su_offset = offset + 33 + name_length
77
+ su_offset += 1 if name_length.even? # Padding byte
78
+
79
+ return unless su_offset < offset + @length
80
+
81
+ @system_use = data[su_offset, offset + @length - su_offset]
82
+ end
83
+
84
+ # Check if entry is a directory
85
+ #
86
+ # @return [Boolean] true if directory
87
+ def directory?
88
+ @flags.anybits?(Iso::FLAG_DIRECTORY)
89
+ end
90
+
91
+ # Check if entry is hidden
92
+ #
93
+ # @return [Boolean] true if hidden
94
+ def hidden?
95
+ @flags.anybits?(Iso::FLAG_HIDDEN)
96
+ end
97
+
98
+ # Check if this is the current directory entry
99
+ #
100
+ # @return [Boolean] true if current directory
101
+ def current_directory?
102
+ @name == "\x00"
103
+ end
104
+
105
+ # Check if this is the parent directory entry
106
+ #
107
+ # @return [Boolean] true if parent directory
108
+ def parent_directory?
109
+ @name == "\x01"
110
+ end
111
+
112
+ # Get file size
113
+ #
114
+ # @return [Integer] Size in bytes
115
+ def size
116
+ @data_length
117
+ end
118
+
119
+ # Get modification time
120
+ #
121
+ # @return [Time, nil] Modification time
122
+ def mtime
123
+ @recording_date
124
+ end
125
+
126
+ private
127
+
128
+ # Parse directory record datetime (7-byte format)
129
+ #
130
+ # @param data [String] 7-byte datetime
131
+ # @return [Time, nil] Parsed time
132
+ def parse_record_datetime(data)
133
+ return nil if data.nil? || data.bytesize < 7
134
+
135
+ year = 1900 + data.getbyte(0)
136
+ month = data.getbyte(1)
137
+ day = data.getbyte(2)
138
+ hour = data.getbyte(3)
139
+ minute = data.getbyte(4)
140
+ second = data.getbyte(5)
141
+ # Timezone offset at byte 6 (15-minute intervals from GMT)
142
+
143
+ Time.new(year, month, day, hour, minute, second)
144
+ rescue ArgumentError
145
+ nil
146
+ end
147
+
148
+ # Parse file identifier name
149
+ def parse_name
150
+ # Special cases for current and parent directory
151
+ return if @name == "\x00" || @name == "\x01"
152
+
153
+ # Remove version number (;1) if present
154
+ @name = @name.split(";").first if @name.include?(";")
155
+
156
+ # Convert to UTF-8 and strip
157
+ @name = @name.force_encoding("UTF-8").strip
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end