1 ;;; base64.el,v --- Base64 encoding functions
2 ;; Author: Kyle E. Jones
3 ;; Created: 1997/03/12 14:37:09
5 ;; Keywords: extensions
7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8 ;;; Copyright (C) 1997 Kyle E. Jones
10 ;;; This file is not part of GNU Emacs, but the same permissions apply.
12 ;;; GNU Emacs is free software; you can redistribute it and/or modify
13 ;;; it under the terms of the GNU General Public License as published by
14 ;;; the Free Software Foundation; either version 2, or (at your option)
15 ;;; any later version.
17 ;;; GNU Emacs is distributed in the hope that it will be useful,
18 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;;; GNU General Public License for more details.
22 ;;; You should have received a copy of the GNU General Public License
23 ;;; along with GNU Emacs; see the file COPYING. If not, write to the
24 ;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25 ;;; Boston, MA 02111-1307, USA.
26 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
28 (eval-when-compile (require 'static))
33 (mel-find-function 'mime-decode-string "base64")
34 (mel-find-function 'mime-decode-region "base64")
35 (mel-find-function 'mime-encode-string "base64")
36 (mel-find-function 'mime-encode-region "base64"))
40 (if (not (fboundp 'char-int))
41 (fset 'char-int 'identity))
43 (defvar base64-alphabet
44 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
46 (defvar base64-decoder-program nil
47 "*Non-nil value should be a string that names a MIME base64 decoder.
48 The program should expect to read base64 data on its standard
49 input and write the converted data to its standard output.")
51 (defvar base64-decoder-switches nil
52 "*List of command line flags passed to the command named by
53 base64-decoder-program.")
55 (defvar base64-encoder-program nil
56 "*Non-nil value should be a string that names a MIME base64 encoder.
57 The program should expect arbitrary data on its standard
58 input and write base64 data to its standard output.")
60 (defvar base64-encoder-switches nil
61 "*List of command line flags passed to the command named by
62 base64-encoder-program.")
64 (defconst base64-alphabet-decoding-alist
66 ( ?A . 00) ( ?B . 01) ( ?C . 02) ( ?D . 03) ( ?E . 04) ( ?F . 05)
67 ( ?G . 06) ( ?H . 07) ( ?I . 08) ( ?J . 09) ( ?K . 10) ( ?L . 11)
68 ( ?M . 12) ( ?N . 13) ( ?O . 14) ( ?P . 15) ( ?Q . 16) ( ?R . 17)
69 ( ?S . 18) ( ?T . 19) ( ?U . 20) ( ?V . 21) ( ?W . 22) ( ?X . 23)
70 ( ?Y . 24) ( ?Z . 25) ( ?a . 26) ( ?b . 27) ( ?c . 28) ( ?d . 29)
71 ( ?e . 30) ( ?f . 31) ( ?g . 32) ( ?h . 33) ( ?i . 34) ( ?j . 35)
72 ( ?k . 36) ( ?l . 37) ( ?m . 38) ( ?n . 39) ( ?o . 40) ( ?p . 41)
73 ( ?q . 42) ( ?r . 43) ( ?s . 44) ( ?t . 45) ( ?u . 46) ( ?v . 47)
74 ( ?w . 48) ( ?x . 49) ( ?y . 50) ( ?z . 51) ( ?0 . 52) ( ?1 . 53)
75 ( ?2 . 54) ( ?3 . 55) ( ?4 . 56) ( ?5 . 57) ( ?6 . 58) ( ?7 . 59)
76 ( ?8 . 60) ( ?9 . 61) ( ?+ . 62) ( ?/ . 63)
79 (defvar base64-alphabet-decoding-vector
80 (let ((v (make-vector 123 nil))
81 (p base64-alphabet-decoding-alist))
83 (aset v (car (car p)) (cdr (car p)))
87 (defvar base64-binary-coding-system 'binary)
89 (defun base64-run-command-on-region (start end output-buffer command
91 (let ((tempfile nil) status errstring default-process-coding-system
92 (coding-system-for-write base64-binary-coding-system)
93 (coding-system-for-read base64-binary-coding-system))
96 (setq tempfile (make-temp-name "base64"))
98 (apply 'call-process-region
100 (list output-buffer tempfile)
102 (cond ((equal status 0) t)
103 ((zerop (save-excursion
104 (set-buffer (find-file-noselect tempfile))
108 (set-buffer (find-file-noselect tempfile))
109 (setq errstring (buffer-string))
111 (cons status errstring)))))
113 (delete-file tempfile)))))
115 (if (string-match "XEmacs" emacs-version)
116 (defalias 'base64-insert-char 'insert-char)
117 (defun base64-insert-char (char &optional count ignored buffer)
118 (if (or (null buffer) (eq buffer (current-buffer)))
119 (insert-char char count)
120 (with-current-buffer buffer
121 (insert-char char count))))
122 (setq base64-binary-coding-system 'no-conversion))
124 (defun base64-decode-region (start end)
126 ;;(message "Decoding base64...")
127 (let ((work-buffer nil)
132 (non-data-chars (concat "^=" base64-alphabet)))
135 (setq work-buffer (generate-new-buffer " *base64-work*"))
136 (buffer-disable-undo work-buffer)
137 (if base64-decoder-program
138 (let* ((binary-process-output t) ; any text already has CRLFs
139 (status (apply 'base64-run-command-on-region
140 start end work-buffer
141 base64-decoder-program
142 base64-decoder-switches)))
143 (if (not (eq status t))
144 (error "%s" (cdr status))))
146 (skip-chars-forward non-data-chars end)
148 (setq inputpos (point))
150 ((> (skip-chars-forward base64-alphabet end) 0)
152 (while (< inputpos lim)
154 (aref base64-alphabet-decoding-vector
155 (char-int (char-after inputpos)))))
156 (setq counter (1+ counter)
157 inputpos (1+ inputpos))
159 (base64-insert-char (lsh bits -16) 1 nil work-buffer)
160 (base64-insert-char (logand (lsh bits -8) 255) 1 nil
162 (base64-insert-char (logand bits 255) 1 nil
164 (setq bits 0 counter 0))
165 (t (setq bits (lsh bits 6)))))))
168 (if (not (zerop counter))
169 (error "at least %d bits missing at end of base64 encoding"
170 (* (- 4 counter) 6)))
172 ((eq (char-after (point)) ?=)
175 (error "at least 2 bits missing at end of base64 encoding"))
177 (base64-insert-char (lsh bits -10) 1 nil work-buffer))
179 (base64-insert-char (lsh bits -16) 1 nil work-buffer)
180 (base64-insert-char (logand (lsh bits -8) 255)
183 (t (skip-chars-forward non-data-chars end)))))
184 (or (markerp end) (setq end (set-marker (make-marker) end)))
186 (insert-buffer-substring work-buffer)
187 (delete-region (point) end))
188 (and work-buffer (kill-buffer work-buffer))))
189 ;;(message "Decoding base64... done")
192 (defun base64-encode-region (start end &optional no-line-break)
194 (message "Encoding base64...")
195 (let ((work-buffer nil)
199 (alphabet base64-alphabet)
203 (setq work-buffer (generate-new-buffer " *base64-work*"))
204 (buffer-disable-undo work-buffer)
205 (if base64-encoder-program
206 (let ((status (apply 'base64-run-command-on-region
207 start end work-buffer
208 base64-encoder-program
209 base64-encoder-switches)))
210 (if (not (eq status t))
211 (error "%s" (cdr status))))
212 (setq inputpos start)
213 (while (< inputpos end)
214 (setq bits (+ bits (char-int (char-after inputpos))))
215 (setq counter (1+ counter))
217 (base64-insert-char (aref alphabet (lsh bits -18)) 1 nil
220 (aref alphabet (logand (lsh bits -12) 63))
223 (aref alphabet (logand (lsh bits -6) 63))
226 (aref alphabet (logand bits 63))
228 (setq cols (+ cols 4))
229 (cond ((and (= cols 72)
231 (base64-insert-char ?\n 1 nil work-buffer)
233 (setq bits 0 counter 0))
234 (t (setq bits (lsh bits 8))))
235 (setq inputpos (1+ inputpos)))
236 ;; write out any remaining bits with appropriate padding
239 (setq bits (lsh bits (- 16 (* 8 counter))))
240 (base64-insert-char (aref alphabet (lsh bits -18)) 1 nil
242 (base64-insert-char (aref alphabet (logand (lsh bits -12) 63))
245 (base64-insert-char ?= 2 nil work-buffer)
246 (base64-insert-char (aref alphabet (logand (lsh bits -6) 63))
248 (base64-insert-char ?= 1 nil work-buffer)))
251 (base64-insert-char ?\n 1 nil work-buffer)))
252 (or (markerp end) (setq end (set-marker (make-marker) end)))
254 (insert-buffer-substring work-buffer)
255 (delete-region (point) end))
256 (and work-buffer (kill-buffer work-buffer))))
257 (message "Encoding base64... done"))
259 (defun base64-encode (string)
261 (set-buffer (get-buffer-create " *base64-encode*"))
264 (base64-encode-region (point-min) (point-max))
265 (skip-chars-backward " \t\r\n")
266 (delete-region (point-max) (point))
269 (kill-buffer (current-buffer)))))
271 (defun base64-decode (string)
273 (set-buffer (get-buffer-create " *base64-decode*"))
276 (base64-decode-region (point-min) (point-max))
277 (goto-char (point-max))
278 (skip-chars-backward " \t\r\n")
279 (delete-region (point-max) (point))
282 (kill-buffer (current-buffer)))))
284 (fset 'base64-decode-string 'base64-decode)
285 (fset 'base64-encode-string 'base64-encode)
287 );; (static-when nil ...