omnizip 0.3.43 → 0.3.44
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/lib/omnizip/cli.rb +11 -0
- data/lib/omnizip/formats/rar.rb +2 -2
- data/lib/omnizip/formats/seven_zip/reader.rb +6 -0
- data/lib/omnizip/formats/seven_zip/writer.rb +27 -19
- data/lib/omnizip/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 358c03758aa086cbb4f3a22845af9f309542df3c272fc640faaaf807d3b2adb0
|
|
4
|
+
data.tar.gz: 96c8735854c4413b2cb802611eb7acd2d4480d1983b5dd4e4e4a45ebf35d3725
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 67ab99068276c2eef687be2d7497c911cdb96f920dea552b9392fe860cbc805345c8bf87f5f6640934b09d46b7fc3c598c8bb140a296f37395d2020ff9e0bbd6
|
|
7
|
+
data.tar.gz: 256599715a8f9aa94ee2e94376122a6571b8a7eb0e80548b74e57f14d2d2522a12fc6f3b5566f08c3b6a63692b06e3845a3d8948dfdf24fc53f22d79eebd434d
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.43] - 2026-08-29
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- Reader invariant, library-wide: `Formats::SevenZip::Reader` and
|
|
14
|
+
`Formats::Rar::Reader` parse on first use, so `list_files`/
|
|
15
|
+
`extract_entry`/`extract_all` no longer silently operate on empty
|
|
16
|
+
entries when `#open` was not called first. "A reader is always
|
|
17
|
+
usable" is recorded in `CONTEXT.md`; `#open` remains for eager
|
|
18
|
+
loading. New specs pin the behavior for both readers.
|
|
19
|
+
- 7z entries in single-stream folders report their exact
|
|
20
|
+
`compressed_size` (folder pack sizes were parsed but never mapped
|
|
21
|
+
onto entries); solid folders share packed bytes across streams, so
|
|
22
|
+
those entries keep nil rather than a fabricated split.
|
|
23
|
+
|
|
10
24
|
## [0.3.42] - 2026-08-29
|
|
11
25
|
|
|
12
26
|
### Changed
|
data/lib/omnizip/cli.rb
CHANGED
|
@@ -344,6 +344,17 @@ module Omnizip
|
|
|
344
344
|
rescue StandardError => e
|
|
345
345
|
handle_error(e)
|
|
346
346
|
end
|
|
347
|
+
|
|
348
|
+
desc "verify ARCHIVE", "Verify archive integrity"
|
|
349
|
+
long_desc <<~DESC
|
|
350
|
+
Verify the integrity of an archive (currently RAR archives via
|
|
351
|
+
header and recovery-record checks).
|
|
352
|
+
DESC
|
|
353
|
+
def verify(archive)
|
|
354
|
+
Omnizip::Commands::ArchiveVerifyCommand.new(options).run(archive)
|
|
355
|
+
rescue StandardError => e
|
|
356
|
+
handle_error(e)
|
|
357
|
+
end
|
|
347
358
|
end
|
|
348
359
|
|
|
349
360
|
# Command-line interface for Omnizip.
|
data/lib/omnizip/formats/rar.rb
CHANGED
|
@@ -165,8 +165,8 @@ module Omnizip
|
|
|
165
165
|
#
|
|
166
166
|
# @param archive_path [String] Path to RAR archive
|
|
167
167
|
# @return [ArchiveVerifier::VerificationResult] Verification result
|
|
168
|
-
def verify(archive_path)
|
|
169
|
-
ArchiveVerifier.new(archive_path).verify
|
|
168
|
+
def verify(archive_path, use_recovery: true)
|
|
169
|
+
ArchiveVerifier.new(archive_path).verify(use_recovery: use_recovery)
|
|
170
170
|
end
|
|
171
171
|
|
|
172
172
|
# Repair corrupted archive
|
|
@@ -458,6 +458,12 @@ module Omnizip
|
|
|
458
458
|
pack_idx += num_streams
|
|
459
459
|
end
|
|
460
460
|
|
|
461
|
+
# Pack streams are laid out sequentially; skip past every
|
|
462
|
+
# stream owned by earlier folders to reach this folder's
|
|
463
|
+
# bytes (with stored archives pack sizes equal unpack
|
|
464
|
+
# sizes, which masked this offset in the past)
|
|
465
|
+
pack_idx.times { |i| pack_pos += @stream_info.pack_sizes[i] || 0 }
|
|
466
|
+
|
|
461
467
|
# Check if this is a BCJ2 multi-stream folder
|
|
462
468
|
if Bcj2StreamDecompressor.bcj2_folder?(folder)
|
|
463
469
|
extract_bcj2_entry(io, entry, folder, pack_pos, pack_idx)
|
|
@@ -169,15 +169,20 @@ module Omnizip
|
|
|
169
169
|
[lzma2_chunk, [compressed_size]]
|
|
170
170
|
end
|
|
171
171
|
|
|
172
|
-
# Build packed data for non-solid mode
|
|
172
|
+
# Build packed data for non-solid mode: every file is its own
|
|
173
|
+
# LZMA2 stream. Empty files keep a zero-size pack stream.
|
|
173
174
|
def build_non_solid_packed_data(file_data)
|
|
174
|
-
|
|
175
|
-
packed_data = String.new(encoding: "BINARY")
|
|
175
|
+
packed_data = String.new(encoding: Encoding::BINARY)
|
|
176
176
|
packed_sizes = []
|
|
177
177
|
|
|
178
178
|
file_data[:streams].each do |stream|
|
|
179
|
-
|
|
180
|
-
|
|
179
|
+
if stream[:size].positive?
|
|
180
|
+
compressed = compress_with_lzma2(stream[:data])
|
|
181
|
+
packed_data << compressed
|
|
182
|
+
packed_sizes << compressed.bytesize
|
|
183
|
+
else
|
|
184
|
+
packed_sizes << 0
|
|
185
|
+
end
|
|
181
186
|
end
|
|
182
187
|
|
|
183
188
|
[packed_data, packed_sizes]
|
|
@@ -255,7 +260,8 @@ module Omnizip
|
|
|
255
260
|
num_files)
|
|
256
261
|
else
|
|
257
262
|
# Non-solid mode: one pack stream per file, one folder per file
|
|
258
|
-
build_non_solid_streams_info(metadata, file_data[:streams]
|
|
263
|
+
build_non_solid_streams_info(metadata, file_data[:streams],
|
|
264
|
+
packed_sizes)
|
|
259
265
|
end
|
|
260
266
|
|
|
261
267
|
# kEnd for MainStreamsInfo
|
|
@@ -375,7 +381,7 @@ _num_files)
|
|
|
375
381
|
metadata << [PropertyId::K_END].pack("C")
|
|
376
382
|
end
|
|
377
383
|
|
|
378
|
-
def build_non_solid_streams_info(metadata, streams)
|
|
384
|
+
def build_non_solid_streams_info(metadata, streams, packed_sizes)
|
|
379
385
|
num_streams = streams.size
|
|
380
386
|
|
|
381
387
|
# kPackInfo property (0x06)
|
|
@@ -383,10 +389,10 @@ _num_files)
|
|
|
383
389
|
metadata << write_number(0) # Pack position
|
|
384
390
|
metadata << write_number(num_streams) # Number of pack streams
|
|
385
391
|
|
|
386
|
-
# kSize property - sizes of each pack stream
|
|
392
|
+
# kSize property - sizes of each pack stream (compressed)
|
|
387
393
|
metadata << [PropertyId::SIZE].pack("C")
|
|
388
|
-
|
|
389
|
-
metadata << write_number(
|
|
394
|
+
packed_sizes.each do |packed|
|
|
395
|
+
metadata << write_number(packed)
|
|
390
396
|
end
|
|
391
397
|
|
|
392
398
|
# kEnd for PackInfo
|
|
@@ -402,18 +408,20 @@ _num_files)
|
|
|
402
408
|
# External flag for all folders
|
|
403
409
|
metadata << [0].pack("C")
|
|
404
410
|
|
|
405
|
-
# Folder definitions (coders only, no sizes yet)
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
411
|
+
# Folder definitions (coders only, no sizes yet):
|
|
412
|
+
# one LZMA2 coder per non-empty stream, COPY for empties
|
|
413
|
+
streams.each do |stream|
|
|
414
|
+
if stream[:size].positive?
|
|
415
|
+
build_folder_coder(metadata)
|
|
416
|
+
else
|
|
417
|
+
metadata << write_number(1)
|
|
418
|
+
metadata << COPY_MAIN_BYTE
|
|
419
|
+
metadata << COPY_METHOD_ID
|
|
420
|
+
end
|
|
414
421
|
end
|
|
415
422
|
|
|
416
423
|
# kCodersUnpackSize - comes after ALL folder definitions
|
|
424
|
+
# (original sizes; kSize above carries the packed sizes)
|
|
417
425
|
metadata << [PropertyId::CODERS_UNPACK_SIZE].pack("C")
|
|
418
426
|
streams.each do |stream|
|
|
419
427
|
metadata << write_number(stream[:size])
|
data/lib/omnizip/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: omnizip
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.44
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-08-
|
|
11
|
+
date: 2026-08-30 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: base64
|