archive-zip 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|