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,244 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Formats
5
+ module Msi
6
+ # MSI Table Parser
7
+ #
8
+ # Parses MSI database tables from OLE streams. MSI uses a column-major
9
+ # storage format where each column's data is stored contiguously.
10
+ #
11
+ # Key tables for file extraction:
12
+ # - File: File entries with name, size, component, sequence
13
+ # - Component: Links files to directories
14
+ # - Directory: Directory hierarchy
15
+ # - Media: Cabinet file references
16
+ class TableParser
17
+ include Omnizip::Formats::Msi::Constants
18
+
19
+ # @return [StringPool] String pool for string lookups
20
+ attr_reader :string_pool
21
+
22
+ # @return [Hash] Parsed tables (table_name => rows)
23
+ attr_reader :tables
24
+
25
+ # @return [Hash] Column definitions (table_name => columns)
26
+ attr_reader :columns
27
+
28
+ # @return [Array<String>] Table names
29
+ attr_reader :table_names
30
+
31
+ # @return [Proc] Stream reader method
32
+ attr_reader :read_stream
33
+
34
+ # Initialize table parser
35
+ #
36
+ # @param string_pool [StringPool] String pool for lookups
37
+ # @param stream_reader [Proc] Method to read streams
38
+ def initialize(string_pool, stream_reader)
39
+ @string_pool = string_pool
40
+ @read_stream = stream_reader
41
+ @tables = {}
42
+ @columns = {}
43
+ @table_names = []
44
+ load_table_list
45
+ load_column_defs
46
+ end
47
+
48
+ # Get table rows
49
+ #
50
+ # @param table_name [String] Table name
51
+ # @return [Array<Hash>] Table rows (each row is a hash of column => value)
52
+ def table(table_name)
53
+ return @tables[table_name] if @tables.key?(table_name)
54
+
55
+ @tables[table_name] = parse_table(table_name)
56
+ end
57
+
58
+ # Get column definitions for table
59
+ #
60
+ # @param table_name [String] Table name
61
+ # @return [Array<Hash>] Column definitions
62
+ def column_defs(table_name)
63
+ @columns[table_name] || []
64
+ end
65
+
66
+ # Check if table exists
67
+ #
68
+ # @param table_name [String] Table name
69
+ # @return [Boolean]
70
+ def table_exists?(table_name)
71
+ @table_names.include?(table_name)
72
+ end
73
+
74
+ private
75
+
76
+ # Load list of table names from _Tables stream
77
+ def load_table_list
78
+ data = @read_stream.call(TABLES_STREAM)
79
+ return if data.nil? || data.empty?
80
+
81
+ # _Tables format: column-major with one column (Table string index)
82
+ # First 2 bytes appear to be header (skip)
83
+ # Then 2-byte string indices for each table name
84
+ return if data.bytesize < 4
85
+
86
+ # Skip first 2 bytes (header), read string indices
87
+ offset = 2
88
+ while offset + 2 <= data.bytesize
89
+ str_idx = data[offset, 2].unpack1("v")
90
+ name = @string_pool[str_idx]
91
+ @table_names << name if name
92
+ offset += 2
93
+ end
94
+ end
95
+
96
+ # Load column definitions from _Columns stream
97
+ def load_column_defs
98
+ data = @read_stream.call(COLUMNS_STREAM)
99
+ return if data.nil? || data.empty?
100
+
101
+ # _Columns format: column-major with 4 columns
102
+ # Column 1: Table (string index, 2 bytes)
103
+ # Column 2: Number (signed short, 2 bytes)
104
+ # Column 3: Name (string index, 2 bytes)
105
+ # Column 4: Type (unsigned short, 2 bytes)
106
+
107
+ # Determine number of rows
108
+ num_rows = data.bytesize / 8 # 4 columns * 2 bytes each
109
+
110
+ # Extract each column (column-major order)
111
+ col_size = num_rows * 2
112
+
113
+ table_col = data[0, col_size].unpack("v*")
114
+ number_col = data[col_size, col_size].unpack("v*")
115
+ name_col = data[col_size * 2, col_size].unpack("v*")
116
+ type_col = data[col_size * 3, col_size].unpack("v*")
117
+
118
+ # Build column definitions per table
119
+ num_rows.times do |i|
120
+ table_name = @string_pool[table_col[i]]
121
+ next unless table_name
122
+
123
+ col_name = @string_pool[name_col[i]]
124
+ next unless col_name
125
+
126
+ # Number column: signed short with nullable bit
127
+ raw_num = number_col[i]
128
+ col_num = raw_num & 0x7FFF
129
+ is_primary_key = raw_num.anybits?(0x8000)
130
+
131
+ # Type column: determine storage width
132
+ type_val = type_col[i]
133
+ col_type = parse_column_type(type_val)
134
+
135
+ @columns[table_name] ||= []
136
+ @columns[table_name] << {
137
+ name: col_name,
138
+ number: col_num,
139
+ type: col_type[:type],
140
+ width: col_type[:width],
141
+ nullable: col_type[:nullable],
142
+ primary_key: is_primary_key,
143
+ }
144
+ end
145
+
146
+ # Sort columns by number for each table
147
+ @columns.each_value do |cols|
148
+ cols.sort_by! { |c| c[:number] }
149
+ end
150
+ end
151
+
152
+ # Parse column type from raw type value
153
+ #
154
+ # Type encoding:
155
+ # - Low byte: length or type code
156
+ # - High byte: type category with nullable bit
157
+ #
158
+ # @param raw [Integer] Raw type value
159
+ # @return [Hash] Parsed type info
160
+ def parse_column_type(raw)
161
+ low_byte = raw & 0xFF
162
+ high_byte = (raw >> 8) & 0xFF
163
+ nullable = high_byte.anybits?(0x80)
164
+ type_id = high_byte & 0x7F
165
+
166
+ # Determine type and width based on type_id
167
+ # Type 1 = int, Type >= 0x10 = string
168
+ if type_id == 1
169
+ # Integer type
170
+ if low_byte == 2
171
+ { type: :i2, width: 2, nullable: nullable }
172
+ else
173
+ { type: :i4, width: 4, nullable: nullable }
174
+ end
175
+ elsif type_id == 2
176
+ # Long integer
177
+ { type: :i4, width: 4, nullable: nullable }
178
+ elsif type_id >= 0x10
179
+ # String type - width is always 2 (string pool index)
180
+ { type: :string, width: 2, nullable: nullable }
181
+ else
182
+ # Default to string
183
+ { type: :string, width: 2, nullable: nullable }
184
+ end
185
+ end
186
+
187
+ # Parse a table stream into rows
188
+ #
189
+ # @param table_name [String] Table name
190
+ # @return [Array<Hash>] Parsed rows
191
+ def parse_table(table_name)
192
+ rows = []
193
+ data = @read_stream.call(table_name)
194
+ return rows if data.nil? || data.empty?
195
+
196
+ column_defs = @columns[table_name]
197
+ return rows if column_defs.nil? || column_defs.empty?
198
+
199
+ # Calculate row count from data size and column widths
200
+ total_width = column_defs.sum { |c| c[:width] }
201
+ return rows if total_width.zero?
202
+
203
+ num_rows = data.bytesize / total_width
204
+
205
+ # Parse column by column (column-major order)
206
+ offset = 0
207
+ rows = Array.new(num_rows) { {} }
208
+
209
+ column_defs.each do |col|
210
+ num_rows.times do |row_idx|
211
+ value = read_column_value(data, offset, col)
212
+ rows[row_idx][col[:name]] = value
213
+ offset += col[:width]
214
+ end
215
+ end
216
+
217
+ rows
218
+ end
219
+
220
+ # Read a single column value from data
221
+ #
222
+ # @param data [String] Raw table data
223
+ # @param offset [Integer] Current offset
224
+ # @param col [Hash] Column definition
225
+ # @return [Object] Parsed value
226
+ def read_column_value(data, offset, col)
227
+ case col[:type]
228
+ when :string
229
+ str_idx = data[offset, 2]&.unpack1("v") || 0
230
+ @string_pool[str_idx]
231
+ when :i2
232
+ val = data[offset, 2]&.unpack1("v") || 0
233
+ # Handle nullable marker
234
+ col[:nullable] ? (val & 0x7FFF) : val
235
+ when :i4
236
+ val = data[offset, 4]&.unpack1("V") || 0
237
+ # Handle nullable marker (high bit)
238
+ col[:nullable] ? (val & 0x7FFFFFFF) : val
239
+ end
240
+ end
241
+ end
242
+ end
243
+ end
244
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Formats
5
+ # MSI (Microsoft Installer) format support
6
+ #
7
+ # Provides read access to MSI packages, extracting files from
8
+ # embedded or external cabinet archives.
9
+ #
10
+ # MSI files are OLE compound documents containing:
11
+ # - Database tables (File, Component, Directory, Media, etc.)
12
+ # - String pool for interned strings
13
+ # - Embedded cabinets (in _Streams or direct OLE streams)
14
+ module Msi
15
+ autoload :Constants, "omnizip/formats/msi/constants"
16
+ autoload :Entry, "omnizip/formats/msi/entry"
17
+ autoload :StringPool, "omnizip/formats/msi/string_pool"
18
+ autoload :TableParser, "omnizip/formats/msi/table_parser"
19
+ autoload :DirectoryResolver, "omnizip/formats/msi/directory_resolver"
20
+ autoload :CabExtractor, "omnizip/formats/msi/cab_extractor"
21
+ autoload :Reader, "omnizip/formats/msi/reader"
22
+
23
+ class << self
24
+ # Open MSI file and return reader
25
+ #
26
+ # @param path [String] Path to MSI file
27
+ # @yield [Reader] Reader instance
28
+ # @return [Reader]
29
+ def open(path)
30
+ reader = Reader.new(path)
31
+ reader.open
32
+ if block_given?
33
+ begin
34
+ yield reader
35
+ ensure
36
+ reader.close
37
+ end
38
+ else
39
+ reader
40
+ end
41
+ end
42
+
43
+ # List files in MSI package
44
+ #
45
+ # @param path [String] Path to MSI file
46
+ # @return [Array<String>] File paths
47
+ def list(path)
48
+ open(path) { |r| r.files.map(&:path) }
49
+ end
50
+
51
+ # Extract all files from MSI package
52
+ #
53
+ # @param path [String] Path to MSI file
54
+ # @param output_dir [String] Output directory
55
+ # @return [Array<String>] Extracted file paths
56
+ def extract(path, output_dir)
57
+ open(path) do |reader|
58
+ reader.extract(output_dir)
59
+ reader.files.map { |f| File.join(output_dir, f.path) }
60
+ end
61
+ end
62
+
63
+ # Get information about MSI package
64
+ #
65
+ # @param path [String] Path to MSI file
66
+ # @return [Hash] Package information
67
+ def info(path)
68
+ open(path, &:info)
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,263 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
4
+
5
+ module Omnizip
6
+ module Formats
7
+ module Ole
8
+ # OLE allocation table
9
+ #
10
+ # Manages block chains for files stored in OLE containers.
11
+ # There are two types: Big (BBAT) and Small (SBAT).
12
+ class AllocationTable
13
+ include Omnizip::Formats::Ole::Constants
14
+
15
+ # @return [Array<Integer>] Table entries
16
+ attr_reader :entries
17
+
18
+ # @return [Object] Parent OLE storage
19
+ attr_reader :ole
20
+
21
+ # @return [IO] Underlying IO
22
+ attr_reader :io
23
+
24
+ # @return [Integer] Block size in bytes
25
+ attr_reader :block_size
26
+
27
+ # Initialize allocation table
28
+ #
29
+ # @param ole [Object] Parent OLE storage
30
+ def initialize(ole)
31
+ @ole = ole
32
+ @entries = []
33
+ end
34
+
35
+ # Load allocation table from binary data
36
+ #
37
+ # @param data [String] Binary data containing table entries
38
+ def load(data)
39
+ @entries = data.unpack("V*")
40
+ end
41
+
42
+ # Get entry at index
43
+ #
44
+ # @param idx [Integer] Entry index
45
+ # @return [Integer] Entry value
46
+ def [](idx)
47
+ @entries[idx]
48
+ end
49
+
50
+ # Set entry at index
51
+ #
52
+ # @param idx [Integer] Entry index
53
+ # @param val [Integer] Entry value
54
+ def []=(idx, val)
55
+ @entries[idx] = val
56
+ end
57
+
58
+ # Get number of entries
59
+ #
60
+ # @return [Integer] Entry count
61
+ def length
62
+ @entries.length
63
+ end
64
+
65
+ # Free resources to prevent memory leaks
66
+ #
67
+ # Call this when done with the allocation table to release memory.
68
+ # @return [void]
69
+ def free
70
+ @entries = nil
71
+ @ole = nil
72
+ @io = nil
73
+ end
74
+
75
+ # Follow chain from starting index
76
+ #
77
+ # @param idx [Integer] Starting block index
78
+ # @return [Array<Integer>] Chain of block indices
79
+ # @raise [ArgumentError] If chain is broken
80
+ def chain(idx)
81
+ result = []
82
+ visited = Set.new
83
+
84
+ until idx >= META_BAT
85
+ if idx.negative? || idx > length
86
+ raise ArgumentError, "Broken allocation chain at index #{idx}"
87
+ end
88
+
89
+ if visited.include?(idx)
90
+ raise ArgumentError, "Circular chain detected at index #{idx}"
91
+ end
92
+
93
+ visited << idx
94
+ result << idx
95
+ idx = @entries[idx]
96
+ end
97
+
98
+ result
99
+ end
100
+
101
+ # Convert block chain to byte ranges
102
+ #
103
+ # @param blocks [Array<Integer>] Block indices
104
+ # @param size [Integer, nil] Optional size to truncate to
105
+ # @return [Array<Array<Integer, Integer>>] Array of [offset, length] pairs
106
+ def blocks_to_ranges(blocks, size = nil)
107
+ return [] if blocks.empty?
108
+
109
+ # Truncate chain if size specified
110
+ blocks = blocks[0, (size.to_f / block_size).ceil] if size
111
+
112
+ # Convert to ranges
113
+ ranges = blocks.map { |i| [block_size * i, block_size] }
114
+
115
+ # Truncate final range if needed
116
+ if ranges.last && size
117
+ ranges.last[1] -= ((ranges.length * block_size) - size)
118
+ end
119
+
120
+ ranges
121
+ end
122
+
123
+ # Get ranges for a chain
124
+ #
125
+ # @param chain_or_idx [Array<Integer>, Integer] Block chain or head index
126
+ # @param size [Integer, nil] Optional size
127
+ # @return [Array<Array<Integer, Integer>>] Byte ranges
128
+ def ranges(chain_or_idx, size = nil)
129
+ blocks = chain_or_idx.is_a?(Array) ? chain_or_idx : chain(chain_or_idx)
130
+ blocks_to_ranges(blocks, size)
131
+ end
132
+
133
+ # Read data from block chain
134
+ #
135
+ # @param chain_or_idx [Array<Integer>, Integer] Block chain or head index
136
+ # @param size [Integer, nil] Optional size
137
+ # @return [String] Data from chain
138
+ def read(chain_or_idx, size = nil)
139
+ ranges = self.ranges(chain_or_idx, size)
140
+ data = "".b
141
+
142
+ ranges.each do |offset, len|
143
+ @io.seek(offset)
144
+ data << @io.read(len).to_s
145
+ end
146
+
147
+ data
148
+ end
149
+
150
+ # Find a free block
151
+ #
152
+ # @return [Integer] Free block index
153
+ def free_block
154
+ idx = @entries.index(AVAIL)
155
+ return idx if idx
156
+
157
+ @entries << AVAIL
158
+ @entries.length - 1
159
+ end
160
+
161
+ # Resize a block chain
162
+ #
163
+ # @param blocks [Array<Integer>] Current blocks (modified in place)
164
+ # @param size [Integer] New size in bytes
165
+ # @return [Array<Integer>] Updated blocks
166
+ def resize_chain(blocks, size)
167
+ new_num_blocks = (size / block_size.to_f).ceil
168
+ old_num_blocks = blocks.length
169
+
170
+ if new_num_blocks < old_num_blocks
171
+ # De-allocate excess blocks
172
+ (new_num_blocks...old_num_blocks).each do |i|
173
+ @entries[blocks[i]] = AVAIL
174
+ end
175
+ if new_num_blocks.positive?
176
+ @entries[blocks[new_num_blocks - 1]] =
177
+ EOC
178
+ end
179
+ blocks.slice!(new_num_blocks..-1)
180
+ elsif new_num_blocks > old_num_blocks
181
+ # Allocate more blocks
182
+ last_block = blocks.last
183
+ (new_num_blocks - old_num_blocks).times do
184
+ block = free_block
185
+ @entries[last_block] = block if last_block
186
+ blocks << block
187
+ last_block = block
188
+ @entries[last_block] = EOC
189
+ end
190
+ end
191
+
192
+ blocks
193
+ end
194
+
195
+ # Truncate table to remove trailing AVAIL entries
196
+ #
197
+ # @return [Array<Integer>] Truncated entries
198
+ def truncate
199
+ temp = @entries.reverse
200
+ first_non_avail = temp.find { |b| b != AVAIL }
201
+ temp = temp[temp.index(first_non_avail)..] if first_non_avail
202
+ temp.reverse
203
+ end
204
+
205
+ # Truncate entries in place
206
+ def truncate_entries
207
+ @entries.replace(truncate)
208
+ end
209
+
210
+ # Pack table to binary data
211
+ #
212
+ # @return [String] Binary data
213
+ def pack
214
+ table = truncate
215
+
216
+ # Pad to block boundary
217
+ num = @ole.bbat.block_size / 4
218
+ if (table.length % num) != 0
219
+ table += [AVAIL] * (num - (table.length % num))
220
+ end
221
+
222
+ table.pack("V*")
223
+ end
224
+
225
+ # Big allocation table (BBAT)
226
+ #
227
+ # Manages large blocks (typically 512 bytes) for files >= 4096 bytes.
228
+ class Big < AllocationTable
229
+ def initialize(ole)
230
+ super
231
+ @block_size = 1 << @ole.header.b_shift
232
+ @io = @ole.io
233
+ end
234
+
235
+ # Big blocks are -1 based to avoid clashing with header
236
+ #
237
+ # @param blocks [Array<Integer>] Block indices
238
+ # @param size [Integer, nil] Optional size
239
+ # @return [Array<Array<Integer, Integer>>] Byte ranges
240
+ def blocks_to_ranges(blocks, size = nil)
241
+ return [] if blocks.empty?
242
+
243
+ blocks = blocks[0, (size.to_f / block_size).ceil] if size
244
+ ranges = blocks.map { |i| [block_size * (i + 1), block_size] }
245
+ ranges.last[1] -= ((ranges.length * block_size) - size) if ranges.last && size
246
+ ranges
247
+ end
248
+ end
249
+
250
+ # Small allocation table (SBAT)
251
+ #
252
+ # Manages small blocks (typically 64 bytes) for files < 4096 bytes.
253
+ class Small < AllocationTable
254
+ def initialize(ole)
255
+ super
256
+ @block_size = 1 << @ole.header.s_shift
257
+ @io = @ole.sb_file
258
+ end
259
+ end
260
+ end
261
+ end
262
+ end
263
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Formats
5
+ module Ole
6
+ # OLE format constants
7
+ #
8
+ # Constants for the OLE compound document format including
9
+ # magic bytes, special markers, and format-related values.
10
+ module Constants
11
+ # OLE magic signature (D0CF11E0A1B11AE1)
12
+ MAGIC = "\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1".b
13
+
14
+ # Header size in bytes
15
+ HEADER_SIZE = 76
16
+
17
+ # Header block size (always 512)
18
+ HEADER_BLOCK_SIZE = 512
19
+
20
+ # Allocation table special markers
21
+ AVAIL = 0xffffffff # Free block
22
+ EOC = 0xfffffffe # End of chain
23
+ BAT = 0xfffffffd # Block stores BAT data
24
+ META_BAT = 0xfffffffc # Block stores Meta BAT
25
+
26
+ # End of tree marker for dirents
27
+ EOT = 0xffffffff
28
+
29
+ # Default threshold for small block vs big block (4096 bytes)
30
+ DEFAULT_THRESHOLD = 4096
31
+
32
+ # Byte order marker for little-endian
33
+ BYTE_ORDER_LE = "\xfe\xff".b
34
+
35
+ # Default block sizes
36
+ DEFAULT_BIG_BLOCK_SHIFT = 9 # 512 bytes
37
+ DEFAULT_SMALL_BLOCK_SHIFT = 6 # 64 bytes
38
+
39
+ # Dirent types
40
+ DIRENT_TYPES = {
41
+ 0 => :empty,
42
+ 1 => :dir,
43
+ 2 => :file,
44
+ 5 => :root,
45
+ }.freeze
46
+
47
+ # Dirent colors for red-black tree
48
+ DIRENT_COLORS = {
49
+ 0 => :red,
50
+ 1 => :black,
51
+ }.freeze
52
+
53
+ # Dirent size in bytes
54
+ DIRENT_SIZE = 128
55
+
56
+ # Maximum name length in UTF-16 characters (including null terminator)
57
+ MAX_NAME_LENGTH = 32
58
+ end
59
+ end
60
+ end
61
+ end