@@ -146,7 +146,158 @@ register-codec [
146
146
result
147
147
]
148
148
149
- ;encode: function [data [binary!]][ ]
149
+ encode: wrap [
150
+ bin: dir: data: date: file: add-data: root: none
151
+ compressed-data: method:
152
+ compressed-size: size: crc: entries: filename-length: offset: 0
153
+
154
+ add-file : func [ file [file! ] /local dir spec] [
155
+ try /except [
156
+ spec: query /mode file [type: date: ]
157
+ either spec [
158
+ file-name: find/tail file root
159
+ either spec/type = 'dir [
160
+ dir: file
161
+ add-data file-name spec
162
+ foreach file read dir [
163
+ add-file dir/: file
164
+ ]
165
+ ][
166
+ add-data file-name reduce [spec/date read file]
167
+ ]
168
+ ][
169
+ ; wildcard?
170
+ dir: first split-path file
171
+ foreach file read file [
172
+ add-file dir/: file
173
+ ]
174
+ ]
175
+ ][
176
+ sys/log/error 'ZIP ["Failed to add file:" as-green file]
177
+ ]
178
+ ]
179
+
180
+ add-data : func [ file spec] [
181
+ sys/log/info 'ZIP ["Adding:" as-green file]
182
+
183
+ any [file? file cause-error 'user 'message reduce [reform ["found" type? file "where file! expected" ]]]
184
+ data: date: none
185
+ compressed-size: size: crc: filename-length: 0
186
+ any [
187
+ all [
188
+ block? spec
189
+ parse spec [any [
190
+ spec:
191
+ date! (date: spec/1 )
192
+ | string! (data: to binary! spec/1 )
193
+ | binary! (data: spec/1 )
194
+ | 1 skip
195
+ ]]
196
+ ]
197
+ all [binary? spec data: spec]
198
+ all [string? spec data: to binary! spec]
199
+ none? spec ; just a directory
200
+ spec = 'none
201
+ ;else..
202
+ all [
203
+ sys/log/error 'ZIP ["Invalid zip file's data specification:" as-red mold /part spec 30 ]
204
+ continue
205
+ ]
206
+ ]
207
+ method: either any [
208
+ none? data
209
+ lesser-or-equal? size: length? data length? compressed-data: compress data
210
+ ][
211
+ compressed-data: data
212
+ 0 ;store
213
+ ][
214
+ compressed-data: copy/part skip compressed-data 2 skip tail compressed-data -8 ;@@ FIXME once compress/zlib will be fixed!
215
+ 8 ;deflate
216
+ ]
217
+
218
+ either compressed-data [
219
+ crc: checksum data 'CRC32
220
+ compressed-size: length? compressed-data
221
+ ][ compressed-data: #{}
222
+ compressed-size: 0
223
+ ]
224
+ if any [
225
+ none? date
226
+ "?date?" = form date ; temp fix for invalid date!
227
+ ][ date: now ]
228
+
229
+ filename-length: length? file
230
+ offset: -1 + index? bin/buffer-write
231
+
232
+ binary/write bin [
233
+ #{ 504B0304 1400 0000 } ;signature / version / flags
234
+ UI16LE :method
235
+ MSDOS-DATETIME :date
236
+ UI32LE :crc
237
+ UI32LE :compressed-size
238
+ UI32LE :size
239
+ UI16LE :filename-length
240
+ UI16LE 0 ; extra
241
+ BYTES :file
242
+ BYTES :compressed-data
243
+ ]
244
+ binary/write dir [
245
+ #{ 504B0102 1400 1400 0000 } ; signature / version made / version needed / flags
246
+ UI16LE :method
247
+ MSDOS-DATETIME :date
248
+ UI32LE :crc
249
+ UI32LE :compressed-size
250
+ UI32LE :size
251
+ 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
258
+ BYTES :file
259
+ ;#{} ; Extra field
260
+ ;#{} ; File comment
261
+ ]
262
+ ++ entries
263
+ ]
264
+
265
+ ;- ENCODE:
266
+ func [
267
+ "Compress given block of files."
268
+ files [block! file! ] "[file! binary! ..] or [file! [date! crc binary!] or [dir! none!] ..]"
269
+ ][
270
+ bin: binary 10000
271
+ dir: binary 1000
272
+ entries: 0
273
+
274
+ either file? files [
275
+ root: first split-path files
276
+ add-file files
277
+ ][
278
+ foreach [file spec] files [
279
+ add-data file spec
280
+ ]
281
+ ]
282
+
283
+ dir-size: length? dir/buffer
284
+ bin-size: length? bin/buffer
285
+
286
+ binary/write bin [
287
+ BYTES : dir/buffer
288
+ #{ 504B0506 } ; End of central directory signature
289
+ UI16LE 0 ; Number of this disk
290
+ UI16LE 0 ; Disk where central directory starts
291
+ UI16LE :entries ; Number of central directory records on this disk
292
+ UI16LE :entries ; Total number of central directory records
293
+ UI32LE :dir-size ; Size of central directory
294
+ UI32LE :bin-size ; Offset of start of central directory
295
+ UI16LE 0 ; Comment length
296
+ ;#{} ; Comment
297
+ ]
298
+ bin/buffer
299
+ ]
300
+ ]
150
301
151
302
identify : function [ data [binary! ]] [
152
303
all [
0 commit comments