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,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Password
5
+ # Validates password strength and requirements
6
+ class PasswordValidator
7
+ attr_reader :min_length, :require_uppercase, :require_lowercase,
8
+ :require_numbers, :require_special
9
+
10
+ # Initialize password validator
11
+ # @param min_length [Integer] Minimum password length
12
+ # @param require_uppercase [Boolean] Require uppercase letters
13
+ # @param require_lowercase [Boolean] Require lowercase letters
14
+ # @param require_numbers [Boolean] Require numbers
15
+ # @param require_special [Boolean] Require special characters
16
+ def initialize(
17
+ min_length: 8,
18
+ require_uppercase: false,
19
+ require_lowercase: false,
20
+ require_numbers: false,
21
+ require_special: false
22
+ )
23
+ @min_length = min_length
24
+ @require_uppercase = require_uppercase
25
+ @require_lowercase = require_lowercase
26
+ @require_numbers = require_numbers
27
+ @require_special = require_special
28
+ end
29
+
30
+ # Validate password
31
+ # @param password [String] Password to validate
32
+ # @return [Boolean] True if valid
33
+ # @raise [ArgumentError] If password is invalid
34
+ def validate(password)
35
+ raise ArgumentError, "Password cannot be nil" if password.nil?
36
+ raise ArgumentError, "Password cannot be empty" if password.empty?
37
+
38
+ check_length(password)
39
+ check_uppercase(password) if require_uppercase
40
+ check_lowercase(password) if require_lowercase
41
+ check_numbers(password) if require_numbers
42
+ check_special(password) if require_special
43
+
44
+ true
45
+ end
46
+
47
+ # Check if password is valid (without raising)
48
+ # @param password [String] Password to check
49
+ # @return [Boolean] True if valid
50
+ def valid?(password)
51
+ validate(password)
52
+ true
53
+ rescue ArgumentError
54
+ false
55
+ end
56
+
57
+ # Get password strength score (0-100)
58
+ # @param password [String] Password to score
59
+ # @return [Integer] Strength score
60
+ def strength(password)
61
+ return 0 if password.nil? || password.empty?
62
+
63
+ score = 0
64
+
65
+ # Length score (up to 40 points)
66
+ score += [password.length * 4, 40].min
67
+
68
+ # Character variety (up to 60 points)
69
+ score += 15 if /[a-z]/.match?(password)
70
+ score += 15 if /[A-Z]/.match?(password)
71
+ score += 15 if /[0-9]/.match?(password)
72
+ score += 15 if /[^a-zA-Z0-9]/.match?(password)
73
+
74
+ [score, 100].min
75
+ end
76
+
77
+ # Get password strength label
78
+ # @param password [String] Password to evaluate
79
+ # @return [Symbol] Strength label (:weak, :fair, :good, :strong)
80
+ def strength_label(password)
81
+ score = strength(password)
82
+
83
+ case score
84
+ when 0...30
85
+ :weak
86
+ when 30...50
87
+ :fair
88
+ when 50...75
89
+ :good
90
+ else
91
+ :strong
92
+ end
93
+ end
94
+
95
+ private
96
+
97
+ def check_length(password)
98
+ return if password.length >= min_length
99
+
100
+ raise ArgumentError,
101
+ "Password too short (minimum: #{min_length} characters)"
102
+ end
103
+
104
+ def check_uppercase(password)
105
+ return if /[A-Z]/.match?(password)
106
+
107
+ raise ArgumentError, "Password must contain uppercase letters"
108
+ end
109
+
110
+ def check_lowercase(password)
111
+ return if /[a-z]/.match?(password)
112
+
113
+ raise ArgumentError, "Password must contain lowercase letters"
114
+ end
115
+
116
+ def check_numbers(password)
117
+ return if /[0-9]/.match?(password)
118
+
119
+ raise ArgumentError, "Password must contain numbers"
120
+ end
121
+
122
+ def check_special(password)
123
+ return if /[^a-zA-Z0-9]/.match?(password)
124
+
125
+ raise ArgumentError, "Password must contain special characters"
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,190 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Password
5
+ # WinZip AES encryption (recommended)
6
+ # Implements WinZip AES-256 encryption standard
7
+ class WinzipAesStrategy < EncryptionStrategy
8
+ # WinZip AES compression method
9
+ COMPRESSION_METHOD = 99 # AES encryption
10
+
11
+ # AES key sizes
12
+ KEY_SIZE_128 = 1
13
+ KEY_SIZE_192 = 2
14
+ KEY_SIZE_256 = 3
15
+
16
+ # Extra field header IDs
17
+ WINZIP_AES_EXTRA_ID = 0x9901
18
+
19
+ attr_reader :key_size, :actual_compression_method
20
+
21
+ # Initialize WinZip AES encryption
22
+ # @param password [String] Password to use
23
+ # @param key_size [Integer] Key size (128, 192, or 256 bits)
24
+ # @param compression_method [Integer] Actual compression method to use
25
+ def initialize(password, key_size: 256, compression_method: 8)
26
+ super(password)
27
+ @key_size = validate_key_size(key_size)
28
+ @actual_compression_method = compression_method
29
+ end
30
+
31
+ # Encrypt data using WinZip AES
32
+ # @param data [String] Data to encrypt
33
+ # @return [String] Encrypted data with authentication
34
+ def encrypt(data)
35
+ require "openssl"
36
+
37
+ # Generate salt
38
+ salt = generate_salt
39
+
40
+ # Derive keys
41
+ encryption_key, password_verify, hmac_key = derive_winzip_keys(salt)
42
+
43
+ # Create cipher
44
+ cipher = OpenSSL::Cipher.new("AES-#{key_bits}-CTR")
45
+ cipher.encrypt
46
+ cipher.key = encryption_key
47
+ cipher.iv = "\x00" * 16 # WinZip AES uses zero IV
48
+
49
+ # Encrypt data
50
+ encrypted = cipher.update(data) + cipher.final
51
+
52
+ # Calculate HMAC
53
+ hmac = calculate_hmac(hmac_key, encrypted)
54
+
55
+ # Return: salt + password_verify + encrypted_data + hmac
56
+ salt + password_verify + encrypted + hmac
57
+ end
58
+
59
+ # Decrypt data using WinZip AES
60
+ # @param data [String] Encrypted data
61
+ # @return [String] Decrypted data
62
+ def decrypt(data)
63
+ require "openssl"
64
+
65
+ # Extract components
66
+ salt_size = salt_length
67
+ salt = data[0, salt_size]
68
+ password_verify_bytes = data[salt_size, 2]
69
+ hmac_size = 10
70
+ encrypted_data = data[(salt_size + 2)...-hmac_size]
71
+ stored_hmac = data[-hmac_size..]
72
+
73
+ # Derive keys
74
+ encryption_key, expected_verify, hmac_key = derive_winzip_keys(salt)
75
+
76
+ # Verify password
77
+ unless password_verify_bytes == expected_verify
78
+ raise Omnizip::PasswordError, "Incorrect password"
79
+ end
80
+
81
+ # Verify HMAC
82
+ calculated_hmac = calculate_hmac(hmac_key, encrypted_data)
83
+ unless stored_hmac == calculated_hmac
84
+ raise Omnizip::PasswordError, "Data integrity check failed"
85
+ end
86
+
87
+ # Decrypt data
88
+ cipher = OpenSSL::Cipher.new("AES-#{key_bits}-CTR")
89
+ cipher.decrypt
90
+ cipher.key = encryption_key
91
+ cipher.iv = "\x00" * 16
92
+
93
+ cipher.update(encrypted_data) + cipher.final
94
+ end
95
+
96
+ # Get compression method for ZIP header
97
+ # @return [Integer] Compression method ID (99 for AES)
98
+ def compression_method
99
+ COMPRESSION_METHOD
100
+ end
101
+
102
+ # Get extra field data for ZIP central directory
103
+ # @return [String] Extra field data
104
+ def extra_field_data
105
+ # WinZip AES extra field format:
106
+ # 2 bytes: extra field ID (0x9901)
107
+ # 2 bytes: data size
108
+ # 2 bytes: AES version (0x0001 or 0x0002)
109
+ # 2 bytes: vendor ID (0x4145 = "AE")
110
+ # 1 byte: AES strength (1=128, 2=192, 3=256)
111
+ # 2 bytes: actual compression method
112
+
113
+ data = [
114
+ 0x0002, # AES version 2
115
+ 0x4145, # Vendor ID "AE"
116
+ key_size_code,
117
+ actual_compression_method,
118
+ ].pack("vvCv")
119
+
120
+ [WINZIP_AES_EXTRA_ID, data.bytesize].pack("vv") + data
121
+ end
122
+
123
+ # Get encryption flags
124
+ # @return [Integer] Encryption flags
125
+ def encryption_flags
126
+ 0x0001 | 0x0040 # Encrypted + strong encryption
127
+ end
128
+
129
+ private
130
+
131
+ def key_bits
132
+ case @key_size
133
+ when KEY_SIZE_128 then 128
134
+ when KEY_SIZE_192 then 192
135
+ when KEY_SIZE_256 then 256
136
+ end
137
+ end
138
+
139
+ def key_size_code
140
+ @key_size
141
+ end
142
+
143
+ def salt_length
144
+ key_bits / 16 # Salt length in bytes
145
+ end
146
+
147
+ def validate_key_size(size)
148
+ case size
149
+ when 128 then KEY_SIZE_128
150
+ when 192 then KEY_SIZE_192
151
+ when 256 then KEY_SIZE_256
152
+ else
153
+ raise ArgumentError,
154
+ "Invalid key size: #{size}. Must be 128, 192, or 256"
155
+ end
156
+ end
157
+
158
+ def generate_salt
159
+ require "securerandom"
160
+ SecureRandom.random_bytes(salt_length)
161
+ end
162
+
163
+ def derive_winzip_keys(salt)
164
+ require "openssl"
165
+
166
+ # WinZip uses PBKDF2 with HMAC-SHA1
167
+ key_material = OpenSSL::PKCS5.pbkdf2_hmac(
168
+ password,
169
+ salt,
170
+ 1000, # iterations
171
+ (2 * key_bits / 8) + 2, # key + hmac + verify
172
+ OpenSSL::Digest.new("SHA1"),
173
+ )
174
+
175
+ key_size_bytes = key_bits / 8
176
+
177
+ encryption_key = key_material[0, key_size_bytes]
178
+ password_verify = key_material[key_size_bytes, 2]
179
+ hmac_key = key_material[(key_size_bytes + 2), key_size_bytes]
180
+
181
+ [encryption_key, password_verify, hmac_key]
182
+ end
183
+
184
+ def calculate_hmac(key, data)
185
+ require "openssl"
186
+ OpenSSL::HMAC.digest(OpenSSL::Digest.new("SHA1"), key, data)[0, 10]
187
+ end
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Password
5
+ # Traditional ZIP encryption (PKWARE)
6
+ # WARNING: This is a weak encryption method and should not be used
7
+ # for sensitive data. Use WinZipAesStrategy instead.
8
+ class ZipCryptoStrategy < EncryptionStrategy
9
+ # ZIP compression method for traditional encryption
10
+ COMPRESSION_METHOD = 0 # Stored (encryption is separate)
11
+
12
+ # Initialize ZIP crypto encryption
13
+ # @param password [String] Password to use
14
+ # @param warn_weak [Boolean] Show security warning (default: true)
15
+ def initialize(password, warn_weak: true)
16
+ super(password)
17
+
18
+ if warn_weak
19
+ warn "WARNING: Traditional ZIP encryption is weak and easily cracked."
20
+ warn "Consider using WinZip AES encryption instead for better security."
21
+ end
22
+ end
23
+
24
+ # Encrypt data using traditional ZIP encryption
25
+ # @param data [String] Data to encrypt
26
+ # @return [String] Encrypted data
27
+ def encrypt(data)
28
+ keys = initialize_keys
29
+
30
+ # Generate encryption header
31
+ header = generate_encryption_header(keys)
32
+
33
+ # Encrypt data with same keys (header generation updated them)
34
+ encrypted = data.bytes.map do |byte|
35
+ temp = decrypt_byte(keys)
36
+ update_keys(keys, byte)
37
+ byte ^ temp
38
+ end
39
+
40
+ (header + encrypted).pack("C*")
41
+ end
42
+
43
+ # Decrypt data using traditional ZIP encryption
44
+ # @param data [String] Data to decrypt
45
+ # @return [String] Decrypted data
46
+ def decrypt(data)
47
+ bytes = data.bytes
48
+ keys = initialize_keys
49
+
50
+ # Skip encryption header (12 bytes)
51
+ header = bytes[0...12]
52
+ encrypted_data = bytes[12..]
53
+
54
+ # Verify header
55
+ header.each { |byte| update_keys(keys, decrypt_byte(keys) ^ byte) }
56
+
57
+ # Decrypt data
58
+ decrypted = encrypted_data.map do |byte|
59
+ temp = decrypt_byte(keys)
60
+ plaintext_byte = byte ^ temp
61
+ update_keys(keys, plaintext_byte)
62
+ plaintext_byte
63
+ end
64
+
65
+ decrypted.pack("C*")
66
+ end
67
+
68
+ # Get compression method for ZIP header
69
+ # @return [Integer] Compression method ID
70
+ def compression_method
71
+ COMPRESSION_METHOD
72
+ end
73
+
74
+ # Get encryption flags
75
+ # @return [Integer] Encryption flags (bit 0 set)
76
+ def encryption_flags
77
+ 0x0001 # Traditional encryption
78
+ end
79
+
80
+ private
81
+
82
+ # Initialize encryption keys
83
+ # @return [Array<Integer>] Initial key values
84
+ def initialize_keys
85
+ keys = [0x12345678, 0x23456789, 0x34567890]
86
+
87
+ password.each_byte do |byte|
88
+ update_keys(keys, byte)
89
+ end
90
+
91
+ keys
92
+ end
93
+
94
+ # Update encryption keys
95
+ # @param keys [Array<Integer>] Current keys
96
+ # @param byte [Integer] Byte to incorporate
97
+ def update_keys(keys, byte)
98
+ keys[0] = crc32_update(keys[0], byte)
99
+ keys[1] =
100
+ (((keys[1] + (keys[0] & 0xFF)) * 134_775_813) + 1) & 0xFFFFFFFF
101
+ keys[2] = crc32_update(keys[2], keys[1] >> 24)
102
+ end
103
+
104
+ # Decrypt a single byte
105
+ # @param keys [Array<Integer>] Current keys
106
+ # @return [Integer] Decrypted byte value
107
+ def decrypt_byte(keys)
108
+ temp = keys[2] | 2
109
+ ((temp * (temp ^ 1)) >> 8) & 0xFF
110
+ end
111
+
112
+ # CRC32 update for key generation
113
+ # @param crc [Integer] Current CRC value
114
+ # @param byte [Integer] Byte to add
115
+ # @return [Integer] Updated CRC
116
+ def crc32_update(crc, byte)
117
+ Omnizip::Checksums::Crc32.new.process_byte(crc, byte)
118
+ end
119
+
120
+ # Generate encryption header
121
+ # @param keys [Array<Integer>] Encryption keys
122
+ # @return [Array<Integer>] 12-byte header
123
+ def generate_encryption_header(keys)
124
+ header = Array.new(12) { rand(256) }
125
+ encrypted_header = []
126
+ header.each do |byte|
127
+ temp = decrypt_byte(keys)
128
+ update_keys(keys, byte)
129
+ encrypted_header << (byte ^ temp)
130
+ end
131
+ encrypted_header
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ # Password protection module
5
+ # Provides encryption and password validation for archives
6
+ module Password
7
+ # Nested classes - autoloaded
8
+ autoload :PasswordValidator, "omnizip/password/password_validator"
9
+ autoload :EncryptionStrategy, "omnizip/password/encryption_strategy"
10
+ autoload :ZipCryptoStrategy, "omnizip/password/zip_crypto_strategy"
11
+ autoload :WinzipAesStrategy, "omnizip/password/winzip_aes_strategy"
12
+ autoload :EncryptionRegistry, "omnizip/password/encryption_registry"
13
+
14
+ class << self
15
+ # Validate a password
16
+ # @param password [String] Password to validate
17
+ # @param options [Hash] Validation options
18
+ # @return [Boolean] True if valid
19
+ def validate(password, **options)
20
+ validator = PasswordValidator.new(**options)
21
+ validator.validate(password)
22
+ end
23
+
24
+ # Check password strength
25
+ # @param password [String] Password to check
26
+ # @return [Symbol] Strength label (:weak, :fair, :good, :strong)
27
+ def strength(password)
28
+ validator = PasswordValidator.new
29
+ validator.strength_label(password)
30
+ end
31
+
32
+ # Create encryption strategy
33
+ # @param method [Symbol] Encryption method
34
+ # @param password [String] Password
35
+ # @param options [Hash] Strategy options
36
+ # @return [EncryptionStrategy] Encryption strategy instance
37
+ def create_strategy(method, password, **options)
38
+ EncryptionRegistry.create(method, password, **options)
39
+ end
40
+
41
+ # Get available encryption methods
42
+ # @return [Array<Symbol>] List of methods
43
+ def encryption_methods
44
+ EncryptionRegistry.strategies
45
+ end
46
+
47
+ # Prompt for password (with confirmation)
48
+ # @param confirm [Boolean] Require confirmation
49
+ # @return [String] Password entered by user
50
+ def prompt(confirm: true)
51
+ require "io/console"
52
+
53
+ print "Enter password: "
54
+ password = $stdin.noecho(&:gets).chomp
55
+ puts
56
+
57
+ if confirm
58
+ print "Confirm password: "
59
+ confirmation = $stdin.noecho(&:gets).chomp
60
+ puts
61
+
62
+ unless password == confirmation
63
+ raise PasswordError, "Passwords do not match"
64
+ end
65
+ end
66
+
67
+ password
68
+ end
69
+
70
+ # Read password from environment variable
71
+ # @param var_name [String] Environment variable name
72
+ # @return [String, nil] Password or nil
73
+ def from_env(var_name = "OMNIZIP_PASSWORD")
74
+ ENV.fetch(var_name, nil)
75
+ end
76
+
77
+ # Read password from file
78
+ # @param file_path [String] Path to password file
79
+ # @return [String] Password from file
80
+ def from_file(file_path)
81
+ File.read(file_path).strip
82
+ end
83
+ end
84
+ end
85
+
86
+ # Password-related error
87
+ class PasswordError < Error; end
88
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omnizip
4
+ module Pipe
5
+ # Stream-based compression for pipe operations
6
+ #
7
+ # Accepts any IO-like input source and writes compressed output
8
+ # to any IO-like sink, using chunk-based processing to avoid
9
+ # loading entire streams into memory.
10
+ #
11
+ # @example Compress stdin to stdout
12
+ # compressor = StreamCompressor.new($stdin, $stdout, :zip)
13
+ # compressor.compress
14
+ #
15
+ # @example Compress with custom chunk size
16
+ # compressor = StreamCompressor.new(
17
+ # input_file,
18
+ # output_file,
19
+ # :zip,
20
+ # chunk_size: 1024 * 1024 # 1MB chunks
21
+ # )
22
+ # compressor.compress
23
+ class StreamCompressor
24
+ # Default chunk size for reading input (64KB)
25
+ DEFAULT_CHUNK_SIZE = 64 * 1024
26
+
27
+ attr_reader :input, :output, :format, :options, :bytes_written
28
+
29
+ # Initialize stream compressor
30
+ #
31
+ # @param input [IO] Input stream to compress
32
+ # @param output [IO] Output stream for compressed data
33
+ # @param format [Symbol] Archive format (:zip, :seven_zip)
34
+ # @param compression [Symbol, nil] Compression algorithm
35
+ # @param options [Hash] Compression options
36
+ # @option options [String] :entry_name Name for entry (default: 'stream.dat')
37
+ # @option options [Integer] :chunk_size Read buffer size
38
+ # @option options [Integer] :level Compression level (1-9)
39
+ # @option options [Proc] :progress Progress callback
40
+ def initialize(input, output, format, compression: nil, **options)
41
+ @input = input
42
+ @output = output
43
+ @format = format
44
+ @compression = compression
45
+ @options = options
46
+ @chunk_size = options[:chunk_size] || DEFAULT_CHUNK_SIZE
47
+ @bytes_read = 0
48
+ @bytes_written = 0
49
+ @progress_callback = options[:progress]
50
+ end
51
+
52
+ # Compress input stream to output stream
53
+ #
54
+ # Reads input in chunks and writes compressed output,
55
+ # maintaining constant memory usage regardless of input size.
56
+ #
57
+ # @return [Integer] Total bytes written to output
58
+ # @raise [ArgumentError] If format is unsupported
59
+ def compress
60
+ case @format
61
+ when :zip
62
+ compress_zip
63
+ when :seven_zip, :"7z"
64
+ compress_7z
65
+ else
66
+ raise ArgumentError, "Unsupported format: #{@format}"
67
+ end
68
+
69
+ @bytes_written
70
+ end
71
+
72
+ private
73
+
74
+ # Compress to ZIP format
75
+ #
76
+ # Creates a single-entry ZIP archive from the input stream.
77
+ # Uses chunked reading to handle arbitrarily large inputs.
78
+ def compress_zip
79
+ entry_name = @options[:entry_name] || "stream.dat"
80
+ level = @options[:level]
81
+
82
+ Omnizip::Zip::OutputStream.open(@output) do |zos|
83
+ # Create entry with optional compression level
84
+ entry_options = {}
85
+ entry_options[:level] = level if level
86
+
87
+ zos.put_next_entry(entry_name, **entry_options)
88
+
89
+ # Stream chunks from input to output
90
+ stream_chunks(zos)
91
+ end
92
+ end
93
+
94
+ # Compress to 7z format
95
+ #
96
+ # Note: 7z streaming support is limited due to format requirements.
97
+ # For full 7z support, use file-based operations.
98
+ def compress_7z
99
+ raise NotImplementedError,
100
+ "7z pipe compression not yet implemented. " \
101
+ "Use file-based operations for 7z format."
102
+ end
103
+
104
+ # Stream data in chunks from input to output
105
+ #
106
+ # @param output_stream [IO] Stream to write chunks to
107
+ def stream_chunks(output_stream)
108
+ loop do
109
+ chunk = @input.read(@chunk_size)
110
+ break unless chunk
111
+
112
+ output_stream.write(chunk)
113
+ @bytes_read += chunk.bytesize
114
+ @bytes_written += chunk.bytesize
115
+
116
+ # Call progress callback if provided
117
+ @progress_callback&.call(@bytes_read, @bytes_written)
118
+ end
119
+ rescue IOError, SystemCallError => e
120
+ raise Omnizip::Error, "Stream compression failed: #{e.message}"
121
+ end
122
+ end
123
+ end
124
+ end