Skip to content

Commit 6952e76

Browse files
author
Ary Borenszweig
committedJan 19, 2017
Zip: explain the meaning of some numeric constants throught the code
1 parent 4e7c5c7 commit 6952e76

File tree

3 files changed

+34
-5
lines changed

3 files changed

+34
-5
lines changed
 

Diff for: ‎src/zip/file.cr

+18-1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ class Zip::File
8181
end
8282
end
8383

84+
# Try to find the directory end offset (by searching its signature)
85+
# in the last 64, 1024 and 65K bytes (in that order)
8486
private def find_directory_end_offset
8587
find_directory_end_offset(64) ||
8688
find_directory_end_offset(1024) ||
@@ -100,6 +102,8 @@ class Zip::File
100102

101103
i = buf_size - 1 - 4
102104
while i >= 0
105+
# These are the bytes the make up the directory end signature,
106+
# according to the spec
103107
break if buf[i] == 0x50 && buf[i + 1] == 0x4b && buf[i + 2] == 0x05 && buf[i + 3] == 0x06
104108
i -= 1
105109
end
@@ -172,17 +176,30 @@ class Zip::File
172176
# Apparently a zip entry might have different extra bytes
173177
# in the local file header and central directory header,
174178
# so to know the data offset we must read them again.
179+
#
180+
# The bytes inside a local file header, from the signature
181+
# and up to the extra length field, sum up 30 bytes.
182+
#
183+
# This 30 and 22 constants are burned inside the zip spec and
184+
# will never change.
175185
@io.read_at(offset.to_i32, 30) do |io|
176-
# at least check that the signature is OK
186+
# at least check that the signature is OK (these are 4 bytes)
177187
signature = read(io, UInt32)
178188
if signature != FileInfo::SIGNATURE
179189
raise Zip::Error.new("wrong local file header signature (expected 0x#{FileInfo::SIGNATURE.to_s(16)}, got 0x#{signature.to_s(16)})")
180190
end
181191

182192
# Skip most of the headers except filename length and extra length
193+
# (skip 22, so we already read 26 bytes)
183194
io.skip(22)
195+
196+
# With these two we read 4 bytes more, so we are at 30 bytes
184197
filename_length = read(io, UInt16)
185198
extra_length = read(io, UInt16)
199+
200+
# The data of this entry comes at the local file header offset
201+
# plus 30 bytes (the ones we just skipped) plus skipping the
202+
# filename's bytes plus skipping the extra bytes.
186203
@offset + 30 + filename_length + extra_length
187204
end
188205
end

Diff for: ‎src/zip/file_info.cr

+2-2
Original file line numberDiff line numberDiff line change
@@ -95,15 +95,15 @@ module Zip::FileInfo
9595
write io, @uncompressed_size # 4
9696
write io, @filename.bytesize.to_u16 # filename length (2)
9797
write io, extra.size.to_u16 # extra field length (2)
98-
24
98+
24 # the 24 bytes we just wrote
9999
end
100100

101101
protected def write_data_descriptor(io : IO)
102102
io.write FileInfo::DEFLATE_END_SIGNATURE # 4
103103
write io, @crc32 # 4
104104
write io, @compressed_size # 4
105105
write io, @uncompressed_size # 4
106-
16
106+
16 # the 16 bytes we just wrote
107107
end
108108

109109
protected def decompressor_for(io, is_sized = false)

Diff for: ‎src/zip/writer.cr

+14-2
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,12 @@ class Zip::Writer
3434
# Creates a new writer to the given *io*.
3535
def initialize(@io : IO, @sync_close = false)
3636
@entries = [] of Entry
37-
@written = 0_u32
3837
@compressed_size_counter = ChecksumWriter.new
3938
@uncompressed_size_counter = ChecksumWriter.new(compute_crc32: true)
39+
40+
# Keep track of how many bytes we write, because we need
41+
# that to write the offset of each local file header and some other info
42+
@written = 0_u32
4043
end
4144

4245
# Creates a new writer to the given *filename*.
@@ -188,16 +191,25 @@ class Zip::Writer
188191
write Zip::CENTRAL_DIRECTORY_HEADER_SIGNATURE # 4
189192
write Zip::VERSION # version made by (2)
190193
write Zip::VERSION # version needed to extract (2)
194+
@written += 8 # the 8 bytes we just wrote
195+
191196
@written += entry.meta_to_io(@io)
197+
192198
write entry.comment.bytesize.to_u16 # file comment length (2)
193199
write 0_u16 # disk number start (2)
194200
write 0_u16 # internal file attribute (2)
195201
write 0_u32 # external file attribute (4)
196202
write entry.offset # relative offset of local header (4)
203+
@written += 14 # the 14 bytes we just wrote
204+
197205
@io << entry.filename
206+
@written += entry.filename.bytesize
207+
198208
@io.write(entry.extra)
209+
@written += entry.extra.size
210+
199211
@io << entry.comment
200-
@written += 22 + entry.filename.bytesize + entry.extra.size + entry.comment.bytesize
212+
@written += entry.comment.bytesize
201213
end
202214
end
203215

0 commit comments

Comments
 (0)
Please sign in to comment.