-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathunmime.lisp
executable file
·68 lines (58 loc) · 2.28 KB
/
unmime.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
":" ; exec cl-launch -Q -sm fare-scripts/unmime -- "$@"
(uiop:define-package :fare-scripts/unmime
(:mix :cl :cl-mime :uiop :optima :optima.ppcre :babel))
(in-package :fare-scripts/unmime)
(defun show-usage (&optional (stream *standard-output*))
(format stream "usage: unmime | unmime - | unmime <filename>~%~
decodes the specified file (default: stdin) as a single-file mime container~%"))
(defun get-parsed-mime (x)
(etypecase x
((or stream string) (cl-mime:parse-mime x))
(pathname (with-input-file (s x) (cl-mime:parse-mime s)))))
(defun decode-text-mime (tm)
(let* ((c (coerce (decode-content tm) '(vector (unsigned-byte 8) *)))
(cs (first (charset tm)))
(e (babel-encodings:get-character-encoding
(and cs (find-symbol (string-upcase cs) :keyword)))))
(octets-to-string c :encoding e)))
(defun get-mime-string (x)
(let* ((m (get-parsed-mime x))
(tm (etypecase m
(text-mime m)
(multipart-mime (let ((f (first (content m))))
(check-type f text-mime)
f)))))
(decode-text-mime tm)))
(defun unmime (x) (princ (get-mime-string x)))
(defun unmimeall (input output-name)
(let ((m (get-parsed-mime input)))
(unmime-to m output-name)))
(defun unmime-to (m output-name)
(etypecase m
(text-mime
(format! t "Creating text file ~A~%" output-name)
(with-output-file (o output-name :if-exists :rename-and-delete)
(princ (decode-text-mime m) o)))
(multipart-mime
(loop
:for i :from 0
:for n :in (content m)
:do (unmime-to n (format nil "~A.~D" output-name i))))
(mime
(format! t "Creating binary file ~A~%" output-name)
(with-output-file (o output-name :element-type '(unsigned-byte 8) :if-exists :rename-and-delete)
(write-sequence (decode-content m) o)))))
(defun main (argv)
(match argv
(() (unmime *standard-input*))
((list x)
(match x
("-" (unmime *standard-input*))
((or "-h" "--help" "-?") (show-usage *standard-output*))
((ppcre "^-") (show-usage *error-output*))
(_ (unmime (parse-native-namestring x)))))
((list in out)
(unmimeall
(if (equal in "-") *standard-input* (parse-native-namestring in))
out))
(_ (show-usage *error-output*))))