Skip to content

Commit 5fa5b83

Browse files
committed
FEAT: updated ZIP codec
* Access to comment and extra field of uncompressed data * Added support to include file comments, extras or insternal and external attributes * Added support to include uncompressed data (useful when making APK targeting version 30 and above)
1 parent f9fe063 commit 5fa5b83

File tree

2 files changed

+52
-20
lines changed

2 files changed

+52
-20
lines changed

src/mezz/codec-zip.reb

+45-20
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@ REBOL [
22
title: "REBOL 3 codec for ZIP files"
33
name: 'codec-zip
44
author: rights: "Oldes"
5-
version: 0.0.3
5+
version: 0.0.4
66
specification: https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
77
history: [
8+
30-Nov-2021 "Oldes" {
9+
* Access to comment and extra field of uncompressed data
10+
* Added support to include file comments, extras or insternal and external attributes
11+
* Added support to include uncompressed data (useful when making APK targeting version 30 and above)
12+
}
813
24-Oct-2019 "Oldes" {
914
* Refactored decoder so it is using central directory structure
1015
* Added decode/info refinement used to resolve just the info about files without decompressing
@@ -78,7 +83,7 @@ register-codec [
7883
cheader: binary/read bin [
7984
UI16LE ; version made by
8085
UI16LE ; version needed to extract
81-
BITSET16 ; general purpose bit flag
86+
flags: BITSET16 ; general purpose bit flag
8287
method: UI16LE ; compression method
8388
modified: MSDOS-DATETIME ; last modified
8489
crc: SI32LE ; crc-32
@@ -131,7 +136,12 @@ register-codec [
131136
sys/log/error 'ZIP ["CRC check failed!" crc "<>" crc2]
132137
]
133138
]
134-
repend result [name reduce [modified data crc]]
139+
data: reduce [modified data crc]
140+
unless empty? extr [append append data quote extra: extr]
141+
unless empty? comm [append append data quote comment: comm]
142+
if att-int <> 0 [append append data quote att-int: att-int]
143+
if att-ext <> 0 [append append data quote att-ext: att-ext]
144+
append/only append result name data
135145
]
136146

137147
if only [
@@ -149,7 +159,7 @@ register-codec [
149159

150160
encode: wrap [
151161
bin: dir: data: date: file: add-data: root: none
152-
compressed-data: method:
162+
compressed-data: method: att-ext: att-int:
153163
compressed-size: size: crc: entries: filename-length: offset: 0
154164

155165
add-file: func[file [file!] /local dir spec][
@@ -178,12 +188,12 @@ register-codec [
178188
]
179189
]
180190

181-
add-data: func[file spec][
191+
add-data: func[file spec /local no-compress? extra extra-length comm comm-length][
182192
sys/log/info 'ZIP ["Adding:" as-green file]
183193

184194
any [file? file cause-error 'user 'message reduce [reform ["found" type? file "where file! expected"]]]
185195
data: date: none
186-
compressed-size: size: crc: filename-length: 0
196+
compressed-size: size: crc: filename-length: extra-length: comm-length: att-ext: att-int: 0
187197
any [
188198
all [
189199
block? spec
@@ -192,6 +202,14 @@ register-codec [
192202
date! (date: spec/1)
193203
| string! (data: to binary! spec/1)
194204
| binary! (data: spec/1)
205+
| 'store (no-compress?: true)
206+
| quote extra: set extra binary! (extra-length: length? extra)
207+
| quote comment: set comm [binary! | any-string!] (
208+
if string? comm [comm: to binary! comm]
209+
comm-length: length? comm
210+
)
211+
| quote att-int: set att-int integer!
212+
| quote att-ext: set att-ext integer!
195213
| 1 skip
196214
]]
197215
]
@@ -205,9 +223,13 @@ register-codec [
205223
continue
206224
]
207225
]
226+
data: any [data #{}]
227+
crc: checksum data 'CRC32
228+
size: length? data
208229
method: either any [
209-
none? data
210-
lesser-or-equal? size: length? data length? compressed-data: compress data 'deflate
230+
no-compress?
231+
zero? size
232+
lesser-or-equal? size length? compressed-data: compress data 'deflate
211233
][
212234
compressed-data: data
213235
0 ;store
@@ -216,18 +238,21 @@ register-codec [
216238
]
217239

218240
either compressed-data [
219-
crc: checksum data 'CRC32
220241
compressed-size: length? compressed-data
221242
][ compressed-data: #{}
222243
compressed-size: 0
223244
]
245+
224246
if any [
225247
none? date
226248
"?date?" = form date ; temp fix for invalid date!
227249
][ date: now ]
228250

229251
filename-length: length? file
230-
offset: -1 + index? bin/buffer-write
252+
offset: indexZ? bin/buffer-write
253+
254+
unless extra [extra: #{}]
255+
unless comm [comm: #{}]
231256

232257
binary/write bin [
233258
#{504B0304 1400 0000} ;signature / version / flags
@@ -242,22 +267,22 @@ register-codec [
242267
BYTES :compressed-data
243268
]
244269
binary/write dir [
245-
#{504B0102 1400 1400 0000} ; signature / version made / version needed / flags
270+
#{504B0102 1703 1400 0000} ; signature / version made / version needed / flags
246271
UI16LE :method
247272
MSDOS-DATETIME :date
248273
UI32LE :crc
249274
UI32LE :compressed-size
250275
UI32LE :size
251276
UI16LE :filename-length
252-
UI16LE 0 ; Extra field length
253-
UI16LE 0 ; File comment length
254-
UI16LE 0 ; Disk number where file starts
255-
UI16LE 0 ; Internal file attributes
256-
UI32LE 0 ; External file attributes
257-
UI32LE :offset ; Relative offset of local file header
277+
UI16LE :extra-length ; Extra field length
278+
UI16LE :comm-length ; File comment length
279+
UI16LE 0 ; Disk number where file starts
280+
UI16LE :att-int ; Internal file attributes
281+
UI32LE :att-ext ; External file attributes
282+
UI32LE :offset ; Relative offset of local file header
258283
BYTES :file
259-
;#{} ; Extra field
260-
;#{} ; File comment
284+
BYTES :extra ; Extra field
285+
BYTES :comm ; File comment
261286
]
262287
++ entries
263288
]
@@ -312,7 +337,7 @@ register-codec [
312337
header [block!] "[method cmp-size unc-size]"
313338
][
314339
bin: binary buffer
315-
unless 67324752 = binary/read bin 'UI32LE [
340+
unless 67324752 = binary/read bin 'UI32LE [ ;#{504B0304}
316341
sys/log/error 'ZIP {Offset is not pointing to the "Local file header"}
317342
return none
318343
]

src/tests/units/codecs-test.r3

+7
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,9 @@ if find codecs 'zip [
272272
%file-2 "Hello, Hello, Hello, Hello, Hello!"
273273
%file-3 #{000102030400010203040001020304}
274274
%folder/file-4 [1-Jan-2021 "This file is with date!"]
275+
%file-5 ["Uncompressed" store] ; this file will be included uncompressed
276+
%file-6 ["This file have a comment" comment: "This file is not important."]
277+
%file-7 ["File with attributes" att-int: 1 att-ext: 2175008768]
275278
]]
276279
data: decode 'ZIP bin
277280
--assert all [
@@ -281,6 +284,10 @@ if find codecs 'zip [
281284
data/5 = %file-2
282285
data/9 = %folder/file-4
283286
data/10/1 = 1-Jan-2021/0:00
287+
"Uncompressed" = to string! second select data %file-5
288+
"This file is not important." = to string! select select data %file-6 'comment
289+
1 = select select data %file-7 'att-int
290+
2175008768 = select select data %file-7 'att-ext
284291
]
285292

286293
--test-- "Encode ZIP using directory"

0 commit comments

Comments
 (0)