Class: Omnizip::Formats::Rar5::Reader

Inherits:
Omnizip::Formats::Rar::RarFormatBase show all
Defined in:
lib/omnizip/formats/rar5/reader.rb

Overview

RAR v5 archive reader

Reads RAR 5.x format archives, parsing headers and extracting file data according to the RAR v5 specification.

RAR 5 uses variable-length integers (vint) and improved header structure.

Examples:

Reading a RAR5 archive

reader = Rar5::Reader.new
File.open("archive.rar", "rb") do |file|
  entries = reader.read_archive(file)
  entries.each { |entry| puts entry.name }
end

Instance Attribute Summary

Attributes inherited from Omnizip::Formats::Rar::RarFormatBase

#spec, #version

Instance Method Summary collapse

Methods inherited from Omnizip::Formats::Rar::RarFormatBase

#block_type_code, #block_type_name, #compress, #compression_method_code, #compression_method_name, #decompress, #dictionary_size_code, #encryption_algorithm, #supports_feature?, #verify_magic_bytes, #write_archive

Constructor Details

#initializeReader

Initialize a RAR v5 reader



27
28
29
# File 'lib/omnizip/formats/rar5/reader.rb', line 27

def initialize
  super("rar5")
end

Instance Method Details

#read_archive(io) ⇒ Array<Entry>

Read a RAR v5 archive

Parameters:

  • io (IO)

    The input stream

Returns:

  • (Array<Entry>)

    The archive entries

Raises:



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/omnizip/formats/rar5/reader.rb', line 36

def read_archive(io)
  unless verify_magic_bytes(io)
    raise FormatError, "Invalid RAR v5 signature"
  end

  # Skip past the magic bytes (8 bytes)
  io.seek(8, ::IO::SEEK_SET)

  entries = []

  # Read main header
  main_header = read_header(io)
  unless main_header.type == block_type_code(:main_header)
    raise FormatError, "Expected main archive header"
  end

  @archive_flags = main_header.flags

  # Skip to end of main header
  skip_to_header_end(io, main_header)

  # Read blocks until end marker or EOF/error
  loop do
    header = read_header(io)
    break if header.type == block_type_code(:end_marker)

    case header.type
    when block_type_code(:file_header)
      entry = read_file_entry(io, header)
      entries << entry if entry
    when block_type_code(:service_header)
      skip_header_data(io, header)
    when block_type_code(:encryption_header)
      read_encryption_header(io, header)
    else
      skip_header_data(io, header)
    end
  rescue EOFError, RangeError, FormatError
    # Truncated or corrupted file - return what we have
    break
  end

  entries
rescue EOFError, RangeError, FormatError
  # Handle truncated/invalid files gracefully
  []
end