git.fiddlerwoaroof.com
Browse code

Various modifications to zipfile parser

Ed Langley authored on 06/08/2018 17:52:59
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))