#!/bin/sh : ; exec klone $0 "$@" ; The above line finds the klone executable in the $PATH ;; coded from the base64.el lisp functions by wmperry (setq args (getopts "USAGE: %0 < input-file > output file decodes base64 data" ("-v" () verbose "verbose operation") )) ;; base64 is RFC 1521 ; A 65-character subset of US-ASCII is used, enabling 6 bits to be represented ; per printable character. (The extra 65th character, "=", is used to signify a ; special processing function.) ; ; The encoding process represents 24-bit groups of input bits as output strings ; of 4 encoded characters. Proceeding from left to right, a 24-bit input group ; is formed by concatenating 3 8-bit input groups. These 24 bits are then ; treated as 4 concatenated 6-bit groups, each of which is translated into a ; single digit in the base64 alphabet. When encoding a bit stream via the base64 ; encoding, the bit stream must be presumed to be ordered with the ; most-significant-bit first. That is, the first bit in the stream will be the ; high-order bit in the first byte, and the eighth bit will be the low-order bit ; in the first byte, and so on. ; ; Each 6-bit group is used as an index into an array of 64 printable ; characters. The character referenced by the index is placed in the output ; string. These characters, identified in Table 1, below, are selected so as to ; be universally representable, and the set excludes characters with particular ; significance to SMTP (e.g., ".", CR, LF) and to the encapsulation boundaries ; defined in this document (e.g., "-"). ; ; Table 1: The Base64 Alphabet ; ; Value Encoding Value Encoding Value Encoding Value Encoding ; 0 A 17 R 34 i 51 z ; 1 B 18 S 35 j 52 0 ; 2 C 19 T 36 k 53 1 ; 3 D 20 U 37 l 54 2 ; 4 E 21 V 38 m 55 3 ; 5 F 22 W 39 n 56 4 ; 6 G 23 X 40 o 57 5 ; 7 H 24 Y 41 p 58 6 ; 8 I 25 Z 42 q 59 7 ; 9 J 26 a 43 r 60 8 ; 10 K 27 b 44 s 61 9 ; 11 L 28 c 45 t 62 + ; 12 M 29 d 46 u 63 / ; 13 N 30 e 47 v ; 14 O 31 f 48 w (pad) = ; 15 P 32 g 49 x ; 16 Q 33 h 50 y ; ; The output stream (encoded bytes) must be represented in lines of no more than ; 76 characters each. All line breaks or other characters not found in Table 1 ; must be ignored by decoding software. In base64 data, characters other than ; those in Table 1, line breaks, and other white space probably indicate a ; transmission error, about which a warning message or even a message rejection ; might be appropriate under some circumstances. ; ; Special processing is performed if fewer than 24 bits are available at the end ; of the data being encoded. A full encoding quantum is always completed at the ; end of a body. When fewer than 24 input bits are available in an input group, ; zero bits are added (on the right) to form an integral number of 6-bit ; groups. Padding at the end of the data is performed using the '=' ; character. Since all base64 input is an integral number of octets, only the ; following cases can arise: (1) the final quantum of encoding input is an ; integral multiple of 24 bits; here, the final unit of encoded output will be ; an integral multiple of 4 characters with no "=" padding, (2) the final ; quantum of encoding input is exactly 8 bits; here, the final unit of encoded ; output will be two characters followed by two "=" padding characters, or (3) ; the final quantum of encoding input is exactly 16 bits; here, the final unit ; of encoded output will be three characters followed by one "=" padding ; character. ; ; Because it is used only for padding at the end of the data, the occurrence of ; any '=' characters may be taken as evidence that the end of the data has been ; reached (without truncation in transit). No such assurance is possible, ; however, when the number of octets transmitted was a multiple of three. ; ; Any characters outside of the base64 alphabet are to be ignored in ; base64-encoded data. The same applies to any illegal sequence of characters in ; the base64 encoding, such as "=====" ; ; Care must be taken to use the proper octets for line breaks if base64 encoding ; is applied directly to text material that has not been converted to canonical ; form. In particular, text line breaks must be converted into CRLF sequences ; prior to base64 encoding. The important thing to note is that this may be done ; directly by the encoder rather than in a prior canonicalization step in some ; implementations. (defvar base64-code-string "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" "Character set used for base64 decoding") (defvar base64-decode-vector (with (vec (vector 256)) (dotimes (i 256) (put vec i (seek base64-code-string i))) vec )) (defvar base64-max-line-length 64) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Base64 decoding functions ;;; Most of the decoding code is courtesy Francesco Potorti` ;;; ;;; this is much faster than my original code - thanks! ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; decode from stdin to stdout (defun base64-decode (in out &aux line outline (re (regcomp "^[ \t]*([ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/]+)[ \t\r]*$")) (endchars 0) code l padding-read ) (catch 'EOF (while t (setq line (read-line in)) (if padding-read (if (/= "" line) (error "trailing garbage after last line!") )) (if (regexec re line) (setq line (regsub re 1))) (if (/= 0 (mod (length line) 4)) (progn ; pad to 4 with = (setq line (+ line (make-string (- 4 (mod (length line) 4)) #\=))) (PF "last line not multiple of 4, padded with =\n") )) (dotimes (n (/ (length line) 4)) (setq l (list)) (dolist (c (subseq line (* n 4) (* (+ n 1) 4))) (lappend l (if (getn base64-decode-vector c) (getn base64-decode-vector c) (= c #\=) (progn (incf endchars) (setq padding-read t) 0) (error "Character %0 does not match Mime base64 coding" c) ))) (setq code (+ (get l 3 0) (logshift (get l 2 0) 6) (logshift (get l 1 0) 12) (logshift (get l 0 0) 18) )) (if (= 0 endchars) (progn (write-char (mod (logshift code -16) 256) out) (write-char (mod (logshift code -8) 256) out) (write-char (mod code 256) out) ) (= 1 endchars) (progn (write-char (mod (logshift code -16) 256) out) (write-char (mod (logshift code -8) 256) out) ) (= 2 endchars) (progn (write-char (mod (logshift code -16) 256) out) ))) ))) (defun main (&aux ) (base64-decode *standard-input* *standard-output*) ) (main) ;;; EMACS MODES ;;; Local Variables: *** ;;; mode:lisp *** ;;; End: ***