Browse code
Various modifications to zipfile parser
Ed Langley authored on 06/08/2018 17:52:59
Showing 1 changed files
Showing 1 changed files
... | ... |
@@ -1,100 +1,35 @@ |
1 | 1 |
(uiop:define-package :fwoar.zipfile |
2 |
- (:mix :cl :fwoar.lisputils) |
|
2 |
+ (:mix :cl :fwoar.lisputils :fwoar.bin-parser) |
|
3 | 3 |
(:export )) |
4 | 4 |
(in-package :fwoar.zipfile) |
5 | 5 |
|
6 |
-(defun read-bytes (n s) |
|
7 |
- (with (seq (make-array n :element-type 'serapeum:octet)) |
|
8 |
- (values seq |
|
9 |
- (read-sequence seq s)))) |
|
10 |
- |
|
11 |
-(defun calculate-sizes (desc) |
|
12 |
- (reduce #'+ desc |
|
13 |
- :key #'cadr |
|
14 |
- :initial-value 0)) |
|
15 |
- |
|
16 |
-(defun le->int (bytes) |
|
17 |
- (cadr |
|
18 |
- (reduce (op (destructuring-bind (count val) _1 |
|
19 |
- (list (1+ count) |
|
20 |
- (+ val |
|
21 |
- (ash _2 |
|
22 |
- (* count 8)))))) |
|
23 |
- bytes |
|
24 |
- :initial-value (list 0 0)))) |
|
25 |
- |
|
26 |
-(defun get-extractable-bytes (desc &optional (bindings ())) |
|
27 |
- (loop for ((name size . other) . rest) on (resolve-sizes desc bindings) |
|
28 |
- until (symbolp size) |
|
29 |
- collect (list* name size other) into extractable |
|
30 |
- finally (return (values extractable |
|
31 |
- (append (serapeum:unsplice |
|
32 |
- (when (symbolp size) |
|
33 |
- (list* name size other))) |
|
34 |
- rest))))) |
|
35 |
- |
|
36 |
-(defun resolve-sizes (desc extant-bindings) |
|
37 |
- (declare (optimize (debug 3))) |
|
38 |
- (loop with bindings = (copy-seq extant-bindings) |
|
39 |
- for (name size . rest) in desc |
|
40 |
- for resolved = (when (symbolp size) |
|
41 |
- (cdr (assoc size bindings))) |
|
42 |
- when resolved do (push (cons name resolved) |
|
43 |
- bindings) |
|
44 |
- if resolved collect (list* name resolved rest) into new-desc |
|
45 |
- else collect (list* name size rest) into new-desc |
|
46 |
- finally (return (values new-desc |
|
47 |
- (remove-duplicates (append (mapcar (op (apply #'cons (subseq _ 0 2))) |
|
48 |
- new-desc) |
|
49 |
- bindings) |
|
50 |
- :key 'car |
|
51 |
- :from-end t))))) |
|
52 |
- |
|
53 |
-(defun extract-bytes (desc bytes) |
|
54 |
- (loop |
|
55 |
- with cur-idx = 0 |
|
56 |
- for (name size . rest) in desc |
|
57 |
- for next-seq = (subseq bytes cur-idx |
|
58 |
- (+ cur-idx size)) |
|
59 |
- collect (cons name (if rest |
|
60 |
- (funcall (car rest) next-seq) |
|
61 |
- next-seq)) |
|
62 |
- do (incf cur-idx size))) |
|
63 |
- |
|
64 |
-(defun parse-struct (desc s) |
|
65 |
- (let* ((struct-size (calculate-sizes desc)) |
|
66 |
- (bytes (read-bytes struct-size s))) |
|
67 |
- (extract-bytes desc bytes))) |
|
6 |
+(defmacro defun* (name (&rest args) &body body) |
|
7 |
+ (let ((defs (cdr (assoc :where body)))) |
|
8 |
+ `(defun ,name ,args |
|
9 |
+ (flet (,@defs) |
|
10 |
+ ,@(loop for form in body until (and (consp form) (eql :where (car form))) |
|
11 |
+ collect form))))) |
|
68 | 12 |
|
69 | 13 |
(defun make-zipfile-stream (fn) |
70 | 14 |
(open fn :element-type '(unsigned-byte 8))) |
71 | 15 |
|
72 |
- |
|
73 |
-(defun extract (raw-desc s &optional bindings) |
|
74 |
- (multiple-value-bind (desc remainder) (get-extractable-bytes raw-desc bindings) |
|
75 |
- (let ((next-segment (parse-struct desc s))) |
|
76 |
- (if remainder |
|
77 |
- (append next-segment |
|
78 |
- (extract remainder s (append next-segment bindings))) |
|
79 |
- next-segment)))) |
|
80 |
- |
|
81 | 16 |
(defparameter *zip-local-file-header* |
82 | 17 |
'((signature 4) |
83 | 18 |
(version 2) |
84 | 19 |
(flags 2) |
85 |
- (compression 2 le->int) |
|
20 |
+ (compression 2 fwoar.bin-parser:le->int) |
|
86 | 21 |
(mod-time 2) |
87 | 22 |
(mod-date 2) |
88 | 23 |
(crc-32 4) |
89 |
- (compressed-size 4 le->int) |
|
90 |
- (uncompressed-size 4 le->int) |
|
91 |
- (file-name-length 2 le->int) |
|
92 |
- (extra-field-length 2 le->int) |
|
24 |
+ (compressed-size 4 fwoar.bin-parser:le->int) |
|
25 |
+ (uncompressed-size 4 fwoar.bin-parser:le->int) |
|
26 |
+ (file-name-length 2 fwoar.bin-parser:le->int) |
|
27 |
+ (extra-field-length 2 fwoar.bin-parser:le->int) |
|
93 | 28 |
(file-name file-name-length babel:octets-to-string) |
94 | 29 |
(extra-field extra-field-length))) |
95 | 30 |
|
96 | 31 |
(defun decode-file-data (metadata s) |
97 |
- (let ((crc-32 (le->int (cdr (assoc 'crc-32 metadata)))) |
|
32 |
+ (let ((crc-32 (fwoar.bin-parser:le->int (cdr (assoc 'crc-32 metadata)))) |
|
98 | 33 |
(compressed-size (cdr (assoc 'compressed-size metadata))) |
99 | 34 |
(uncompressed-size (cdr (assoc 'uncompressed-size metadata)))) |
100 | 35 |
(when (= 0 (+ crc-32 compressed-size uncompressed-size)) |