archive-zip 0.3.0 → 0.4.0
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.
- data/HACKING +25 -42
- data/NEWS +25 -0
- data/README +2 -2
- data/Rakefile +202 -0
- data/TODO +5 -0
- data/default.mspec +8 -0
- data/lib/archive/support/binary_stringio.rb +23 -0
- data/lib/archive/support/integer.rb +13 -0
- data/lib/archive/support/io-like.rb +3 -1
- data/lib/archive/support/ioextensions.rb +16 -0
- data/lib/archive/support/iowindow.rb +10 -18
- data/lib/archive/support/time.rb +2 -0
- data/lib/archive/support/zlib.rb +298 -71
- data/lib/archive/zip.rb +161 -139
- data/lib/archive/zip/codec.rb +2 -0
- data/lib/archive/zip/codec/deflate.rb +59 -11
- data/lib/archive/zip/codec/null_encryption.rb +75 -14
- data/lib/archive/zip/codec/store.rb +75 -26
- data/lib/archive/zip/codec/traditional_encryption.rb +146 -35
- data/lib/archive/zip/data_descriptor.rb +6 -4
- data/lib/archive/zip/entry.rb +184 -132
- data/lib/archive/zip/error.rb +2 -0
- data/lib/archive/zip/extra_field.rb +20 -6
- data/lib/archive/zip/extra_field/extended_timestamp.rb +141 -60
- data/lib/archive/zip/extra_field/raw.rb +70 -12
- data/lib/archive/zip/extra_field/unix.rb +58 -16
- data/lib/archive/zip/version.rb +6 -0
- data/spec/archive/zip/codec/deflate/compress/checksum_spec.rb +42 -0
- data/spec/archive/zip/codec/deflate/compress/close_spec.rb +44 -0
- data/spec/archive/zip/codec/deflate/compress/crc32_spec.rb +21 -0
- data/spec/archive/zip/codec/deflate/compress/data_descriptor_spec.rb +67 -0
- data/spec/archive/zip/codec/deflate/compress/new_spec.rb +37 -0
- data/spec/archive/zip/codec/deflate/compress/open_spec.rb +46 -0
- data/spec/archive/zip/codec/deflate/compress/write_spec.rb +109 -0
- data/spec/archive/zip/codec/deflate/decompress/checksum_spec.rb +18 -0
- data/spec/archive/zip/codec/deflate/decompress/close_spec.rb +33 -0
- data/spec/archive/zip/codec/deflate/decompress/crc32_spec.rb +18 -0
- data/spec/archive/zip/codec/deflate/decompress/data_descriptor_spec.rb +67 -0
- data/spec/archive/zip/codec/deflate/decompress/new_spec.rb +14 -0
- data/spec/archive/zip/codec/deflate/decompress/open_spec.rb +27 -0
- data/spec/archive/zip/codec/deflate/fixtures/classes.rb +25 -0
- data/spec/archive/zip/codec/deflate/fixtures/compressed_file.bin +1 -0
- data/spec/archive/zip/codec/deflate/fixtures/compressed_file_nocomp.bin +0 -0
- data/spec/archive/zip/codec/deflate/fixtures/raw_file.txt +10 -0
- data/spec/archive/zip/codec/null_encryption/decrypt/close_spec.rb +33 -0
- data/spec/archive/zip/codec/null_encryption/decrypt/new_spec.rb +14 -0
- data/spec/archive/zip/codec/null_encryption/decrypt/open_spec.rb +27 -0
- data/spec/archive/zip/codec/null_encryption/decrypt/read_spec.rb +24 -0
- data/spec/archive/zip/codec/null_encryption/decrypt/rewind_spec.rb +25 -0
- data/spec/archive/zip/codec/null_encryption/decrypt/seek_spec.rb +57 -0
- data/spec/archive/zip/codec/null_encryption/decrypt/tell_spec.rb +21 -0
- data/spec/archive/zip/codec/null_encryption/encrypt/close_spec.rb +33 -0
- data/spec/archive/zip/codec/null_encryption/encrypt/new_spec.rb +14 -0
- data/spec/archive/zip/codec/null_encryption/encrypt/open_spec.rb +27 -0
- data/spec/archive/zip/codec/null_encryption/encrypt/rewind_spec.rb +26 -0
- data/spec/archive/zip/codec/null_encryption/encrypt/seek_spec.rb +50 -0
- data/spec/archive/zip/codec/null_encryption/encrypt/tell_spec.rb +29 -0
- data/spec/archive/zip/codec/null_encryption/encrypt/write_spec.rb +29 -0
- data/spec/archive/zip/codec/null_encryption/fixtures/classes.rb +12 -0
- data/spec/archive/zip/codec/null_encryption/fixtures/raw_file.txt +10 -0
- data/spec/archive/zip/codec/store/compress/close_spec.rb +33 -0
- data/spec/archive/zip/codec/store/compress/data_descriptor_spec.rb +68 -0
- data/spec/archive/zip/codec/store/compress/new_spec.rb +14 -0
- data/spec/archive/zip/codec/store/compress/open_spec.rb +27 -0
- data/spec/archive/zip/codec/store/compress/rewind_spec.rb +26 -0
- data/spec/archive/zip/codec/store/compress/seek_spec.rb +50 -0
- data/spec/archive/zip/codec/store/compress/tell_spec.rb +29 -0
- data/spec/archive/zip/codec/store/compress/write_spec.rb +29 -0
- data/spec/archive/zip/codec/store/decompress/close_spec.rb +33 -0
- data/spec/archive/zip/codec/store/decompress/data_descriptor_spec.rb +68 -0
- data/spec/archive/zip/codec/store/decompress/new_spec.rb +14 -0
- data/spec/archive/zip/codec/store/decompress/open_spec.rb +27 -0
- data/spec/archive/zip/codec/store/decompress/read_spec.rb +24 -0
- data/spec/archive/zip/codec/store/decompress/rewind_spec.rb +25 -0
- data/spec/archive/zip/codec/store/decompress/seek_spec.rb +57 -0
- data/spec/archive/zip/codec/store/decompress/tell_spec.rb +21 -0
- data/spec/archive/zip/codec/store/fixtures/classes.rb +12 -0
- data/spec/archive/zip/codec/store/fixtures/raw_file.txt +10 -0
- data/spec/archive/zip/codec/traditional_encryption/decrypt/close_spec.rb +64 -0
- data/spec/archive/zip/codec/traditional_encryption/decrypt/new_spec.rb +18 -0
- data/spec/archive/zip/codec/traditional_encryption/decrypt/open_spec.rb +39 -0
- data/spec/archive/zip/codec/traditional_encryption/decrypt/read_spec.rb +126 -0
- data/spec/archive/zip/codec/traditional_encryption/decrypt/rewind_spec.rb +38 -0
- data/spec/archive/zip/codec/traditional_encryption/decrypt/seek_spec.rb +82 -0
- data/spec/archive/zip/codec/traditional_encryption/decrypt/tell_spec.rb +25 -0
- data/spec/archive/zip/codec/traditional_encryption/encrypt/close_spec.rb +64 -0
- data/spec/archive/zip/codec/traditional_encryption/encrypt/new_spec.rb +18 -0
- data/spec/archive/zip/codec/traditional_encryption/encrypt/open_spec.rb +39 -0
- data/spec/archive/zip/codec/traditional_encryption/encrypt/rewind_spec.rb +41 -0
- data/spec/archive/zip/codec/traditional_encryption/encrypt/seek_spec.rb +75 -0
- data/spec/archive/zip/codec/traditional_encryption/encrypt/tell_spec.rb +42 -0
- data/spec/archive/zip/codec/traditional_encryption/encrypt/write_spec.rb +127 -0
- data/spec/archive/zip/codec/traditional_encryption/fixtures/classes.rb +27 -0
- data/spec/archive/zip/codec/traditional_encryption/fixtures/encrypted_file.bin +0 -0
- data/spec/archive/zip/codec/traditional_encryption/fixtures/raw_file.txt +10 -0
- data/spec/binary_stringio/new_spec.rb +34 -0
- data/spec/binary_stringio/set_encoding_spec.rb +14 -0
- data/spec/ioextensions/read_exactly_spec.rb +50 -0
- data/spec/zlib/fixtures/classes.rb +65 -0
- data/spec/zlib/fixtures/compressed_file.bin +1 -0
- data/spec/zlib/fixtures/compressed_file_gzip.bin +0 -0
- data/spec/zlib/fixtures/compressed_file_huffman.bin +2 -0
- data/spec/zlib/fixtures/compressed_file_minmem.bin +0 -0
- data/spec/zlib/fixtures/compressed_file_minwin.bin +1 -0
- data/spec/zlib/fixtures/compressed_file_nocomp.bin +0 -0
- data/spec/zlib/fixtures/compressed_file_raw.bin +1 -0
- data/spec/zlib/fixtures/raw_file.txt +10 -0
- data/spec/zlib/zreader/checksum_spec.rb +40 -0
- data/spec/zlib/zreader/close_spec.rb +14 -0
- data/spec/zlib/zreader/compressed_size_spec.rb +18 -0
- data/spec/zlib/zreader/new_spec.rb +41 -0
- data/spec/zlib/zreader/open_spec.rb +49 -0
- data/spec/zlib/zreader/read_spec.rb +47 -0
- data/spec/zlib/zreader/rewind_spec.rb +23 -0
- data/spec/zlib/zreader/seek_spec.rb +55 -0
- data/spec/zlib/zreader/tell_spec.rb +21 -0
- data/spec/zlib/zreader/uncompressed_size_spec.rb +18 -0
- data/spec/zlib/zwriter/checksum_spec.rb +41 -0
- data/spec/zlib/zwriter/close_spec.rb +14 -0
- data/spec/zlib/zwriter/compressed_size_spec.rb +19 -0
- data/spec/zlib/zwriter/new_spec.rb +64 -0
- data/spec/zlib/zwriter/open_spec.rb +68 -0
- data/spec/zlib/zwriter/rewind_spec.rb +26 -0
- data/spec/zlib/zwriter/seek_spec.rb +54 -0
- data/spec/zlib/zwriter/tell_spec.rb +29 -0
- data/spec/zlib/zwriter/uncompressed_size_spec.rb +19 -0
- data/spec/zlib/zwriter/write_spec.rb +28 -0
- data/spec_helper.rb +49 -0
- metadata +296 -74
- data/MANIFEST +0 -27
- data/lib/archive/support/io.rb +0 -14
- data/lib/archive/support/stringio.rb +0 -22
data/lib/archive/zip/error.rb
CHANGED
|
@@ -1,17 +1,31 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
1
3
|
module Archive; class Zip
|
|
2
4
|
module ExtraField
|
|
3
5
|
# A Hash used to map extra field header identifiers to extra field classes.
|
|
4
6
|
EXTRA_FIELDS = {}
|
|
5
7
|
|
|
6
8
|
# Returns an instance of an extra field class by selecting the class using
|
|
7
|
-
# _header_id_ and passing _data_ to the class'
|
|
8
|
-
# no mapping from a given value of _header_id_ to an extra field
|
|
9
|
-
# instance of Archive::Zip::Entry::ExtraField::Raw is returned.
|
|
10
|
-
def self.
|
|
9
|
+
# _header_id_ and passing _data_ to the class' _parse_central_ method. If
|
|
10
|
+
# there is no mapping from a given value of _header_id_ to an extra field
|
|
11
|
+
# class, an instance of Archive::Zip::Entry::ExtraField::Raw is returned.
|
|
12
|
+
def self.parse_central(header_id, data)
|
|
13
|
+
if EXTRA_FIELDS.has_key?(header_id) then
|
|
14
|
+
EXTRA_FIELDS[header_id].parse_central(data)
|
|
15
|
+
else
|
|
16
|
+
Raw.parse_central(header_id, data)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Returns an instance of an extra field class by selecting the class using
|
|
21
|
+
# _header_id_ and passing _data_ to the class' _parse_local_ method. If
|
|
22
|
+
# there is no mapping from a given value of _header_id_ to an extra field
|
|
23
|
+
# class, an instance of Archive::Zip::Entry::ExtraField::Raw is returned.
|
|
24
|
+
def self.parse_local(header_id, data)
|
|
11
25
|
if EXTRA_FIELDS.has_key?(header_id) then
|
|
12
|
-
EXTRA_FIELDS[header_id].
|
|
26
|
+
EXTRA_FIELDS[header_id].parse_local(data)
|
|
13
27
|
else
|
|
14
|
-
Raw.
|
|
28
|
+
Raw.parse_local(header_id, data)
|
|
15
29
|
end
|
|
16
30
|
end
|
|
17
31
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
1
3
|
require 'archive/zip/error'
|
|
2
4
|
|
|
3
5
|
module Archive; class Zip; module ExtraField
|
|
@@ -12,90 +14,169 @@ module Archive; class Zip; module ExtraField
|
|
|
12
14
|
# Register this extra field for use.
|
|
13
15
|
EXTRA_FIELDS[ID] = self
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"invalid size for extended timestamp: #{data.size}"
|
|
26
|
-
end
|
|
27
|
-
flags, *times = data.unpack('C' + 'V' * ((data.size - 1) / 4))
|
|
28
|
-
mtime = nil
|
|
29
|
-
atime = nil
|
|
30
|
-
crtime = nil
|
|
31
|
-
if flags & 0b001 != 0 then
|
|
32
|
-
if times.size == 0 then
|
|
33
|
-
# Report an error if the flags indicate that the last modified time
|
|
34
|
-
# field should be present when it is not.
|
|
17
|
+
class << self
|
|
18
|
+
# This method signature is part of the interface contract expected by
|
|
19
|
+
# Archive::Zip::Entry for extra field objects.
|
|
20
|
+
#
|
|
21
|
+
# Parses _data_ which is expected to be a String formatted according to
|
|
22
|
+
# the documentation provided with InfoZip's sources.
|
|
23
|
+
#
|
|
24
|
+
# Raises Archive::Zip::ExtraFieldError if _data_ contains invalid data.
|
|
25
|
+
def parse_central(data)
|
|
26
|
+
unless data.size == 5 || data.size == 9 || data.size == 13 then
|
|
35
27
|
raise Zip::ExtraFieldError,
|
|
36
|
-
|
|
28
|
+
"invalid size for extended timestamp: #{data.size}"
|
|
37
29
|
end
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
30
|
+
flags, *times = data.unpack('CV*')
|
|
31
|
+
mtime = nil
|
|
32
|
+
atime = nil
|
|
33
|
+
crtime = nil
|
|
34
|
+
if flags & 0b001 != 0 then
|
|
35
|
+
if times.size == 0 then
|
|
36
|
+
# Report an error if the flags indicate that the last modified time
|
|
37
|
+
# field should be present when it is not.
|
|
38
|
+
raise Zip::ExtraFieldError,
|
|
39
|
+
'corrupt extended timestamp: last modified time field not present'
|
|
40
|
+
end
|
|
41
|
+
mtime = Time.at(times.shift)
|
|
42
|
+
end
|
|
43
|
+
if flags & 0b010 != 0 then
|
|
44
|
+
# If parsing the central file record version of this field, this flag
|
|
45
|
+
# may be set without having the corresponding time value.
|
|
46
|
+
# Use the time value if available, but ignore it if it's missing.
|
|
47
|
+
if times.size > 0 then
|
|
48
|
+
atime = Time.at(times.shift)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
if flags & 0b100 != 0 then
|
|
52
|
+
# If parsing the central file record version of this field, this flag
|
|
53
|
+
# may be set without having the corresponding time value.
|
|
54
|
+
# Use the time value if available, but ignore it if it's missing.
|
|
55
|
+
if times.size > 0 then
|
|
56
|
+
crtime = Time.at(times.shift)
|
|
57
|
+
end
|
|
48
58
|
end
|
|
59
|
+
new(mtime, atime, crtime)
|
|
49
60
|
end
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
61
|
+
|
|
62
|
+
# This method signature is part of the interface contract expected by
|
|
63
|
+
# Archive::Zip::Entry for extra field objects.
|
|
64
|
+
#
|
|
65
|
+
# Parses _data_ which is expected to be a String formatted according to
|
|
66
|
+
# the documentation provided with InfoZip's sources.
|
|
67
|
+
#
|
|
68
|
+
# Raises Archive::Zip::ExtraFieldError if _data_ contains invalid data.
|
|
69
|
+
def parse_local(data)
|
|
70
|
+
unless data.size == 5 || data.size == 9 || data.size == 13 then
|
|
54
71
|
raise Zip::ExtraFieldError,
|
|
55
|
-
|
|
72
|
+
"invalid size for extended timestamp: #{data.size}"
|
|
73
|
+
end
|
|
74
|
+
flags, *times = data.unpack('CV*')
|
|
75
|
+
mtime = nil
|
|
76
|
+
atime = nil
|
|
77
|
+
crtime = nil
|
|
78
|
+
if flags & 0b001 != 0 then
|
|
79
|
+
if times.size == 0 then
|
|
80
|
+
# Report an error if the flags indicate that the last modified time
|
|
81
|
+
# field should be present when it is not.
|
|
82
|
+
raise Zip::ExtraFieldError,
|
|
83
|
+
'corrupt extended timestamp: last modified time field not present'
|
|
84
|
+
end
|
|
85
|
+
mtime = Time.at(times.shift)
|
|
86
|
+
end
|
|
87
|
+
if flags & 0b010 != 0 then
|
|
88
|
+
if times.size == 0 then
|
|
89
|
+
# Report an error if the flags indicate that the last modified time
|
|
90
|
+
# field should be present when it is not.
|
|
91
|
+
raise Zip::ExtraFieldError,
|
|
92
|
+
'corrupt extended timestamp: last accessed time field not present'
|
|
93
|
+
end
|
|
94
|
+
atime = Time.at(times.shift)
|
|
95
|
+
end
|
|
96
|
+
if flags & 0b100 != 0 then
|
|
97
|
+
if times.size == 0 then
|
|
98
|
+
# Report an error if the flags indicate that the file creation time
|
|
99
|
+
# field should be present when it is not.
|
|
100
|
+
raise Zip::ExtraFieldError,
|
|
101
|
+
'corrupt extended timestamp: file creation time field not present'
|
|
102
|
+
end
|
|
103
|
+
crtime = Time.at(times.shift)
|
|
56
104
|
end
|
|
57
|
-
|
|
105
|
+
new(mtime, atime, crtime)
|
|
58
106
|
end
|
|
59
|
-
new(mtime, atime, crtime)
|
|
60
107
|
end
|
|
61
108
|
|
|
62
109
|
# Creates a new instance of this class. _mtime_, _atime_, and _crtime_
|
|
63
110
|
# should be Time instances or +nil+. When set to +nil+ the field is
|
|
64
111
|
# considered to be unset and will not be stored in the archive.
|
|
65
112
|
def initialize(mtime, atime, crtime)
|
|
66
|
-
@
|
|
67
|
-
|
|
68
|
-
|
|
113
|
+
@header_id = ID
|
|
114
|
+
self.mtime = mtime unless mtime.nil?
|
|
115
|
+
self.atime = atime unless atime.nil?
|
|
116
|
+
self.crtime = crtime unless crtime.nil?
|
|
69
117
|
end
|
|
70
118
|
|
|
71
|
-
#
|
|
119
|
+
# Returns the header ID for this ExtraField.
|
|
120
|
+
attr_reader :header_id
|
|
121
|
+
# The last modified time for an entry. Set to either a Time instance or
|
|
122
|
+
# +nil+.
|
|
72
123
|
attr_accessor :mtime
|
|
73
|
-
# The last accessed time for an entry.
|
|
124
|
+
# The last accessed time for an entry. Set to either a Time instance or
|
|
125
|
+
# +nil+.
|
|
74
126
|
attr_accessor :atime
|
|
75
|
-
# The creation time for an entry.
|
|
127
|
+
# The creation time for an entry. Set to either a Time instance or +nil+.
|
|
76
128
|
attr_accessor :crtime
|
|
77
129
|
|
|
78
130
|
# This method signature is part of the interface contract expected by
|
|
79
131
|
# Archive::Zip::Entry for extra field objects.
|
|
80
132
|
#
|
|
81
|
-
#
|
|
82
|
-
#
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
flags |= 0b001
|
|
88
|
-
times << mtime.to_i
|
|
89
|
-
end
|
|
90
|
-
unless atime.nil? then
|
|
91
|
-
flags |= 0b010
|
|
92
|
-
times << atime.to_i
|
|
93
|
-
end
|
|
94
|
-
unless crtime.nil? then
|
|
95
|
-
flags |= 0b100
|
|
96
|
-
times << crtime.to_i
|
|
133
|
+
# Merges the attributes of _other_ into this object and returns +self+.
|
|
134
|
+
#
|
|
135
|
+
# Raises ArgumentError if _other_ is not the same class as this object.
|
|
136
|
+
def merge(other)
|
|
137
|
+
if self.class != other.class then
|
|
138
|
+
raise ArgumentError, "#{self.class} is not the same as #{other.class}"
|
|
97
139
|
end
|
|
140
|
+
|
|
141
|
+
@mtime = other.mtime unless other.mtime.nil?
|
|
142
|
+
@atime = other.atime unless other.atime.nil?
|
|
143
|
+
@crtime = other.crtime unless other.crtime.nil?
|
|
144
|
+
|
|
145
|
+
self
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# This method signature is part of the interface contract expected by
|
|
149
|
+
# Archive::Zip::Entry for extra field objects.
|
|
150
|
+
#
|
|
151
|
+
# Returns a String suitable to writing to a central file record in a ZIP
|
|
152
|
+
# archive file which contains the data for this object.
|
|
153
|
+
def dump_central
|
|
154
|
+
times = []
|
|
155
|
+
times << mtime.to_i unless mtime.nil?
|
|
98
156
|
([ID, 4 * times.size + 1, flags] + times).pack('vvC' + 'V' * times.size)
|
|
99
157
|
end
|
|
158
|
+
|
|
159
|
+
# This method signature is part of the interface contract expected by
|
|
160
|
+
# Archive::Zip::Entry for extra field objects.
|
|
161
|
+
#
|
|
162
|
+
# Returns a String suitable to writing to a local file record in a ZIP
|
|
163
|
+
# archive file which contains the data for this object.
|
|
164
|
+
def dump_local
|
|
165
|
+
times = []
|
|
166
|
+
times << mtime.to_i unless mtime.nil?
|
|
167
|
+
times << atime.to_i unless atime.nil?
|
|
168
|
+
times << crtime.to_i unless crtime.nil?
|
|
169
|
+
([ID, 4 * times.size + 1, flags] + times).pack('vvC' + 'V' * times.size)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
private
|
|
173
|
+
|
|
174
|
+
def flags
|
|
175
|
+
flags = 0
|
|
176
|
+
flags |= 0b001 unless mtime.nil?
|
|
177
|
+
flags |= 0b010 unless atime.nil?
|
|
178
|
+
flags |= 0b100 unless crtime.nil?
|
|
179
|
+
flags
|
|
180
|
+
end
|
|
100
181
|
end
|
|
101
182
|
end; end; end
|
|
@@ -1,32 +1,90 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
1
3
|
module Archive; class Zip; module ExtraField
|
|
2
4
|
# Archive::Zip::Entry::ExtraField::Raw represents an unknown extra field. It
|
|
3
5
|
# is used to store extra fields the Archive::Zip library does not directly
|
|
4
6
|
# support.
|
|
7
|
+
#
|
|
8
|
+
# Do not use this class directly. Define a new class which supports the extra
|
|
9
|
+
# field of interest directly instead.
|
|
5
10
|
class Raw
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
new
|
|
11
|
+
class << self
|
|
12
|
+
# Simply stores _header_id_ and _data_ for later reproduction by
|
|
13
|
+
# #dump_central.
|
|
14
|
+
# This is essentially and alias for #new.
|
|
15
|
+
def parse_central(header_id, data)
|
|
16
|
+
new(header_id, data, true)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Simply stores _header_id_ and _data_ for later reproduction by
|
|
20
|
+
# #dump_local.
|
|
21
|
+
# This is essentially and alias for #new.
|
|
22
|
+
def parse_local(header_id, data)
|
|
23
|
+
new(header_id, data, false)
|
|
24
|
+
end
|
|
10
25
|
end
|
|
11
26
|
|
|
12
|
-
# Simply stores _header_id_ and _data_ for later reproduction by
|
|
13
|
-
|
|
27
|
+
# Simply stores _header_id_ and _data_ for later reproduction by
|
|
28
|
+
# #dump_central or #dump_local. _central_record_ indicates that this field
|
|
29
|
+
# resides in the central file record for an entry when +true+. When
|
|
30
|
+
# +false+, it indicates that this field resides in the local file record for
|
|
31
|
+
# an entry.
|
|
32
|
+
def initialize(header_id, data, central_record)
|
|
14
33
|
@header_id = header_id
|
|
15
|
-
@
|
|
34
|
+
@central_record_data = []
|
|
35
|
+
@local_record_data = []
|
|
36
|
+
if central_record then
|
|
37
|
+
@central_record_data << data
|
|
38
|
+
else
|
|
39
|
+
@local_record_data << data
|
|
40
|
+
end
|
|
16
41
|
end
|
|
17
42
|
|
|
18
43
|
# Returns the header ID for this ExtraField.
|
|
19
44
|
attr_reader :header_id
|
|
20
45
|
# Returns the data contained within this ExtraField.
|
|
21
|
-
attr_reader :
|
|
46
|
+
attr_reader :central_record_data
|
|
47
|
+
attr_reader :local_record_data
|
|
48
|
+
|
|
49
|
+
# This method signature is part of the interface contract expected by
|
|
50
|
+
# Archive::Zip::Entry for extra field objects.
|
|
51
|
+
#
|
|
52
|
+
# Merges the attributes of _other_ into this object and returns +self+.
|
|
53
|
+
#
|
|
54
|
+
# Raises ArgumentError if _other_ does not have the same header ID as this
|
|
55
|
+
# object.
|
|
56
|
+
def merge(other)
|
|
57
|
+
if header_id != other.header_id then
|
|
58
|
+
raise ArgumentError,
|
|
59
|
+
"Header ID mismatch: #{header_id} != #{other.header_id}"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
@central_record_data += other.central_record_data
|
|
63
|
+
@local_record_data += other.local_record_data
|
|
64
|
+
|
|
65
|
+
self
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# This method signature is part of the interface contract expected by
|
|
69
|
+
# Archive::Zip::Entry for extra field objects.
|
|
70
|
+
#
|
|
71
|
+
# Returns a String suitable to writing to a central file record in a ZIP
|
|
72
|
+
# archive file which contains the data for this object.
|
|
73
|
+
def dump_central
|
|
74
|
+
@central_record_data.collect do |data|
|
|
75
|
+
[header_id, data.size].pack('vv') + data
|
|
76
|
+
end
|
|
77
|
+
end
|
|
22
78
|
|
|
23
79
|
# This method signature is part of the interface contract expected by
|
|
24
80
|
# Archive::Zip::Entry for extra field objects.
|
|
25
81
|
#
|
|
26
|
-
# Returns a String suitable to writing to a
|
|
27
|
-
# the data for this object.
|
|
28
|
-
def
|
|
29
|
-
|
|
82
|
+
# Returns a String suitable to writing to a local file record in a ZIP
|
|
83
|
+
# archive file which contains the data for this object.
|
|
84
|
+
def dump_local
|
|
85
|
+
@local_record_data.collect do |data|
|
|
86
|
+
[header_id, data.size].pack('vv') + data
|
|
87
|
+
end
|
|
30
88
|
end
|
|
31
89
|
end
|
|
32
90
|
end; end; end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
1
3
|
require 'archive/zip/error'
|
|
2
4
|
|
|
3
5
|
module Archive; class Zip; module ExtraField
|
|
@@ -17,28 +19,32 @@ module Archive; class Zip; module ExtraField
|
|
|
17
19
|
# Register this extra field for use.
|
|
18
20
|
EXTRA_FIELDS[ID] = self
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
class << self
|
|
23
|
+
# This method signature is part of the interface contract expected by
|
|
24
|
+
# Archive::Zip::Entry for extra field objects.
|
|
25
|
+
#
|
|
26
|
+
# Parses _data_ which is expected to be a String formatted according to
|
|
27
|
+
# the official ZIP specification.
|
|
28
|
+
#
|
|
29
|
+
# Raises Archive::Zip::ExtraFieldError if _data_ contains invalid data.
|
|
30
|
+
def parse_central(data)
|
|
31
|
+
unless data.length >= 12 then
|
|
32
|
+
raise Zip::ExtraFieldError, "invalid size for Unix data: #{data.size}"
|
|
33
|
+
end
|
|
34
|
+
atime, mtime, uid, gid, rest = data.unpack('VVvva')
|
|
35
|
+
new(Time.at(mtime), Time.at(atime), uid, gid, rest)
|
|
30
36
|
end
|
|
31
|
-
|
|
32
|
-
new(Time.at(mtime), Time.at(atime), uid, gid, rest)
|
|
37
|
+
alias :parse_local :parse_central
|
|
33
38
|
end
|
|
34
39
|
|
|
35
40
|
# Creates a new instance of this class. _mtime_ and _atime_ should be Time
|
|
36
|
-
# instances. _uid_ and _gid_ should be user and group
|
|
41
|
+
# instances. _uid_ and _gid_ should be user and group IDs as Integers
|
|
37
42
|
# respectively. _data_ should be a string containing either major and minor
|
|
38
43
|
# device numbers consecutively packed as little endian, 4-byte, unsigned
|
|
39
44
|
# integers (see the _V_ directive of Array#pack) or a path to use as a link
|
|
40
45
|
# target.
|
|
41
46
|
def initialize(mtime, atime, uid, gid, data = '')
|
|
47
|
+
@header_id = ID
|
|
42
48
|
@mtime = mtime
|
|
43
49
|
@atime = atime
|
|
44
50
|
@uid = uid
|
|
@@ -46,6 +52,8 @@ module Archive; class Zip; module ExtraField
|
|
|
46
52
|
@data = data
|
|
47
53
|
end
|
|
48
54
|
|
|
55
|
+
# Returns the header ID for this ExtraField.
|
|
56
|
+
attr_reader :header_id
|
|
49
57
|
# A Time object representing the last accessed time for an entry.
|
|
50
58
|
attr_accessor :atime
|
|
51
59
|
# A Time object representing the last modified time for an entry.
|
|
@@ -85,9 +93,38 @@ module Archive; class Zip; module ExtraField
|
|
|
85
93
|
# This method signature is part of the interface contract expected by
|
|
86
94
|
# Archive::Zip::Entry for extra field objects.
|
|
87
95
|
#
|
|
88
|
-
#
|
|
89
|
-
#
|
|
90
|
-
|
|
96
|
+
# Merges the attributes of _other_ into this object and returns +self+.
|
|
97
|
+
#
|
|
98
|
+
# Raises ArgumentError if _other_ is not the same class as this object.
|
|
99
|
+
def merge(other)
|
|
100
|
+
if self.class != other.class then
|
|
101
|
+
raise ArgumentError, "#{self.class} is not the same as #{other.class}"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
@atime = other.atime
|
|
105
|
+
@mtime = other.mtime
|
|
106
|
+
@uid = other.uid
|
|
107
|
+
@gid = other.gid
|
|
108
|
+
@data = other.data
|
|
109
|
+
|
|
110
|
+
self
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# This method signature is part of the interface contract expected by
|
|
114
|
+
# Archive::Zip::Entry for extra field objects.
|
|
115
|
+
#
|
|
116
|
+
# Returns a String suitable to writing to a central file record in a ZIP
|
|
117
|
+
# archive file which contains the data for this object.
|
|
118
|
+
def dump_central
|
|
119
|
+
''
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# This method signature is part of the interface contract expected by
|
|
123
|
+
# Archive::Zip::Entry for extra field objects.
|
|
124
|
+
#
|
|
125
|
+
# Returns a String suitable to writing to a local file record in a ZIP
|
|
126
|
+
# archive file which contains the data for this object.
|
|
127
|
+
def dump_local
|
|
91
128
|
[
|
|
92
129
|
ID,
|
|
93
130
|
12 + @data.size,
|
|
@@ -97,5 +134,10 @@ module Archive; class Zip; module ExtraField
|
|
|
97
134
|
@gid
|
|
98
135
|
].pack('vvVVvv') + @data
|
|
99
136
|
end
|
|
137
|
+
alias :dump_local :dump_central
|
|
138
|
+
|
|
139
|
+
protected
|
|
140
|
+
|
|
141
|
+
attr_reader :data
|
|
100
142
|
end
|
|
101
143
|
end; end; end
|