Class: Omnizip::Formats::Zip::CentralDirectoryHeader

Inherits:
Object
  • Object
show all
Includes:
Constants
Defined in:
lib/omnizip/formats/zip/central_directory_header.rb

Overview

ZIP Central Directory File Header

Constant Summary

Constants included from Constants

Omnizip::Formats::Zip::Constants::ATTR_ARCHIVE, Omnizip::Formats::Zip::Constants::ATTR_DIRECTORY, Omnizip::Formats::Zip::Constants::CENTRAL_DIRECTORY_SIGNATURE, Omnizip::Formats::Zip::Constants::COMPRESSION_BZIP2, Omnizip::Formats::Zip::Constants::COMPRESSION_DEFLATE, Omnizip::Formats::Zip::Constants::COMPRESSION_DEFLATE64, Omnizip::Formats::Zip::Constants::COMPRESSION_IMPLODED, Omnizip::Formats::Zip::Constants::COMPRESSION_LZMA, Omnizip::Formats::Zip::Constants::COMPRESSION_PPMD, Omnizip::Formats::Zip::Constants::COMPRESSION_REDUCED_1, Omnizip::Formats::Zip::Constants::COMPRESSION_REDUCED_2, Omnizip::Formats::Zip::Constants::COMPRESSION_REDUCED_3, Omnizip::Formats::Zip::Constants::COMPRESSION_REDUCED_4, Omnizip::Formats::Zip::Constants::COMPRESSION_SHRUNK, Omnizip::Formats::Zip::Constants::COMPRESSION_STORE, Omnizip::Formats::Zip::Constants::COMPRESSION_ZSTANDARD, Omnizip::Formats::Zip::Constants::DATA_DESCRIPTOR_SIGNATURE, Omnizip::Formats::Zip::Constants::END_OF_CENTRAL_DIRECTORY_SIGNATURE, Omnizip::Formats::Zip::Constants::FLAG_DATA_DESCRIPTOR, Omnizip::Formats::Zip::Constants::FLAG_ENCRYPTED, Omnizip::Formats::Zip::Constants::FLAG_STRONG_ENCRYPTION, Omnizip::Formats::Zip::Constants::FLAG_UTF8, Omnizip::Formats::Zip::Constants::LOCAL_FILE_HEADER_SIGNATURE, Omnizip::Formats::Zip::Constants::MAX_COMMENT_LENGTH, Omnizip::Formats::Zip::Constants::UNIX_DIR_PERMISSIONS, Omnizip::Formats::Zip::Constants::UNIX_EXTRA_FIELD_TAG, Omnizip::Formats::Zip::Constants::UNIX_FILE_PERMISSIONS, Omnizip::Formats::Zip::Constants::UNIX_SYMLINK_PERMISSIONS, Omnizip::Formats::Zip::Constants::VERSION_BZIP2, Omnizip::Formats::Zip::Constants::VERSION_DEFAULT, Omnizip::Formats::Zip::Constants::VERSION_DEFLATE, Omnizip::Formats::Zip::Constants::VERSION_LZMA, Omnizip::Formats::Zip::Constants::VERSION_MADE_BY_UNIX, Omnizip::Formats::Zip::Constants::VERSION_MADE_BY_WINDOWS, Omnizip::Formats::Zip::Constants::VERSION_ZIP64, Omnizip::Formats::Zip::Constants::ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIGNATURE, Omnizip::Formats::Zip::Constants::ZIP64_END_OF_CENTRAL_DIRECTORY_SIGNATURE, Omnizip::Formats::Zip::Constants::ZIP64_EXTRA_FIELD_TAG, Omnizip::Formats::Zip::Constants::ZIP64_LIMIT

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(signature: CENTRAL_DIRECTORY_SIGNATURE, version_made_by: VERSION_MADE_BY_UNIX, version_needed: VERSION_DEFAULT, flags: 0, compression_method: COMPRESSION_STORE, last_mod_time: 0, last_mod_date: 0, crc32: 0, compressed_size: 0, uncompressed_size: 0, filename_length: 0, extra_field_length: 0, comment_length: 0, disk_number_start: 0, internal_attributes: 0, external_attributes: 0, local_header_offset: 0, filename: "", extra_field: "", comment: "") ⇒ CentralDirectoryHeader

Returns a new instance of CentralDirectoryHeader.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 18

def initialize(
  signature: CENTRAL_DIRECTORY_SIGNATURE,
  version_made_by: VERSION_MADE_BY_UNIX,
  version_needed: VERSION_DEFAULT,
  flags: 0,
  compression_method: COMPRESSION_STORE,
  last_mod_time: 0,
  last_mod_date: 0,
  crc32: 0,
  compressed_size: 0,
  uncompressed_size: 0,
  filename_length: 0,
  extra_field_length: 0,
  comment_length: 0,
  disk_number_start: 0,
  internal_attributes: 0,
  external_attributes: 0,
  local_header_offset: 0,
  filename: "",
  extra_field: "",
  comment: ""
)
  @signature = signature
  @version_made_by = version_made_by
  @version_needed = version_needed
  @flags = flags
  @compression_method = compression_method
  @last_mod_time = last_mod_time
  @last_mod_date = last_mod_date
  @crc32 = crc32
  @compressed_size = compressed_size
  @uncompressed_size = uncompressed_size
  @filename_length = filename_length
  @extra_field_length = extra_field_length
  @comment_length = comment_length
  @disk_number_start = disk_number_start
  @internal_attributes = internal_attributes
  @external_attributes = external_attributes
  @local_header_offset = local_header_offset
  @filename = filename
  @extra_field = extra_field
  @comment = comment
end

Instance Attribute Details

#cached_original_dataObject

Returns the value of attribute cached_original_data.



10
11
12
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 10

def cached_original_data
  @cached_original_data
end

#commentObject

Returns the value of attribute comment.



10
11
12
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 10

def comment
  @comment
end

#comment_lengthObject

Returns the value of attribute comment_length.



10
11
12
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 10

def comment_length
  @comment_length
end

#compressed_sizeObject

Returns the value of attribute compressed_size.



10
11
12
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 10

def compressed_size
  @compressed_size
end

#compression_methodObject

Returns the value of attribute compression_method.



10
11
12
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 10

def compression_method
  @compression_method
end

#crc32Object

Returns the value of attribute crc32.



10
11
12
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 10

def crc32
  @crc32
end

#disk_number_startObject

Returns the value of attribute disk_number_start.



10
11
12
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 10

def disk_number_start
  @disk_number_start
end

#external_attributesObject

Returns the value of attribute external_attributes.



10
11
12
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 10

def external_attributes
  @external_attributes
end

#extra_fieldObject

Returns the value of attribute extra_field.



10
11
12
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 10

def extra_field
  @extra_field
end

#extra_field_lengthObject

Returns the value of attribute extra_field_length.



10
11
12
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 10

def extra_field_length
  @extra_field_length
end

#filenameObject

Returns the value of attribute filename.



10
11
12
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 10

def filename
  @filename
end

#filename_lengthObject

Returns the value of attribute filename_length.



10
11
12
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 10

def filename_length
  @filename_length
end

#flagsObject

Returns the value of attribute flags.



10
11
12
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 10

def flags
  @flags
end

#internal_attributesObject

Returns the value of attribute internal_attributes.



10
11
12
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 10

def internal_attributes
  @internal_attributes
end

#last_mod_dateObject

Returns the value of attribute last_mod_date.



10
11
12
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 10

def last_mod_date
  @last_mod_date
end

#last_mod_timeObject

Returns the value of attribute last_mod_time.



10
11
12
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 10

def last_mod_time
  @last_mod_time
end

#local_header_offsetObject

Returns the value of attribute local_header_offset.



10
11
12
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 10

def local_header_offset
  @local_header_offset
end

#signatureObject

Returns the value of attribute signature.



10
11
12
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 10

def signature
  @signature
end

#uncompressed_sizeObject

Returns the value of attribute uncompressed_size.



10
11
12
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 10

def uncompressed_size
  @uncompressed_size
end

#version_made_byObject

Returns the value of attribute version_made_by.



10
11
12
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 10

def version_made_by
  @version_made_by
end

#version_neededObject

Returns the value of attribute version_needed.



10
11
12
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 10

def version_needed
  @version_needed
end

Class Method Details

.from_binary(data) ⇒ Object

Parse from binary data



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 170

def self.from_binary(data)
  signature, version_made_by, version_needed, flags,
  compression_method, last_mod_time, last_mod_date,
  crc32, compressed_size, uncompressed_size,
  filename_length, extra_field_length, comment_length,
  disk_number_start, internal_attributes,
  external_attributes, local_header_offset = data.unpack("VvvvvvvVVVvvvvvVV")

  unless signature == CENTRAL_DIRECTORY_SIGNATURE
    raise Omnizip::FormatError,
          "Invalid central directory signature"
  end

  offset = 46
  filename = data[offset, filename_length].force_encoding("UTF-8")
  offset += filename_length

  extra_field = data[offset, extra_field_length]
  offset += extra_field_length

  comment = data[offset, comment_length].force_encoding("UTF-8")

  new(
    signature: signature,
    version_made_by: version_made_by,
    version_needed: version_needed,
    flags: flags,
    compression_method: compression_method,
    last_mod_time: last_mod_time,
    last_mod_date: last_mod_date,
    crc32: crc32,
    compressed_size: compressed_size,
    uncompressed_size: uncompressed_size,
    filename_length: filename_length,
    extra_field_length: extra_field_length,
    comment_length: comment_length,
    disk_number_start: disk_number_start,
    internal_attributes: internal_attributes,
    external_attributes: external_attributes,
    local_header_offset: local_header_offset,
    filename: filename,
    extra_field: extra_field,
    comment: comment,
  )
end

Instance Method Details

#directory?Boolean

Returns:

  • (Boolean)


93
94
95
96
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 93

def directory?
  filename.end_with?("/") ||
    external_attributes.anybits?(ATTR_DIRECTORY)
end

#encrypted?Boolean

Check if entry is encrypted

Returns:

  • (Boolean)


107
108
109
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 107

def encrypted?
  flags.anybits?(FLAG_ENCRYPTED)
end

#entry_directory?Boolean

Returns:

  • (Boolean)


81
82
83
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 81

def entry_directory?
  directory?
end

#entry_mtimeObject



89
90
91
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 89

def entry_mtime
  time
end

#entry_nameObject

Omnizip::Entry contract



77
78
79
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 77

def entry_name
  filename
end

#entry_sizeObject



85
86
87
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 85

def entry_size
  uncompressed_size
end

#header_sizeObject

Size of the header in bytes



217
218
219
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 217

def header_size
  46 + filename_length + extra_field_length + comment_length
end

Get link target from Unix extra field



132
133
134
135
136
137
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 132

def link_target
  return nil unless symlink?

  unix_field = UnixExtraField.find_in_extra_field(extra_field)
  unix_field&.link_target
end

#symlink?Boolean

Check if this is a symbolic link

Returns:

  • (Boolean)


127
128
129
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 127

def symlink?
  (unix_permissions & 0o170000) == 0o120000
end

#timeObject

Check if this is a directory entry DOS date/time (as stored in the central directory) to Time



64
65
66
67
68
69
70
71
72
73
74
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 64

def time
  year = ((last_mod_date >> 9) & 0x7F) + 1980
  month = (last_mod_date >> 5) & 0x0F
  day = last_mod_date & 0x1F
  hour = (last_mod_time >> 11) & 0x1F
  minute = (last_mod_time >> 5) & 0x3F
  second = (last_mod_time & 0x1F) * 2
  Time.new(year, month, day, hour, minute, second)
rescue ArgumentError
  nil
end

#to_binaryObject

Serialize to binary format



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 140

def to_binary
  @filename_length = filename.bytesize
  @extra_field_length = extra_field.bytesize
  @comment_length = comment.bytesize

  [
    signature,
    version_made_by,
    version_needed,
    flags,
    compression_method,
    last_mod_time,
    last_mod_date,
    crc32,
    compressed_size,
    uncompressed_size,
    filename_length,
    extra_field_length,
    comment_length,
    disk_number_start,
    internal_attributes,
    external_attributes,
    local_header_offset,
  ].pack("VvvvvvvVVVvvvvvVV") +
    filename.b +
    extra_field.b +
    comment.b
end

#unix_permissionsObject

Get Unix permissions from external attributes



117
118
119
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 117

def unix_permissions
  (external_attributes >> 16) & 0xFFFF
end

#unix_permissions=(perms) ⇒ Object

Set Unix permissions in external attributes



122
123
124
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 122

def unix_permissions=(perms)
  @external_attributes = (perms << 16) | (external_attributes & 0xFFFF)
end

#utf8?Boolean

Check if UTF-8 encoding is used

Returns:

  • (Boolean)


112
113
114
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 112

def utf8?
  flags.anybits?(FLAG_UTF8)
end

#zip64?Boolean

Check if ZIP64 format is needed

Returns:

  • (Boolean)


99
100
101
102
103
104
# File 'lib/omnizip/formats/zip/central_directory_header.rb', line 99

def zip64?
  compressed_size == ZIP64_LIMIT ||
    uncompressed_size == ZIP64_LIMIT ||
    local_header_offset == ZIP64_LIMIT ||
    disk_number_start == 0xFFFF
end