Mercurial > hg > xemacs-beta
comparison lisp/w3/base64.el @ 82:6a378aca36af r20-0b91
Import from CVS: tag r20-0b91
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:07:36 +0200 |
parents | 0293115a14e9 |
children | e04119814345 |
comparison
equal
deleted
inserted
replaced
81:ebca3d831cea | 82:6a378aca36af |
---|---|
1 ;;; base64.el,v --- Base64 encoding functions | 1 ;;; base64.el,v --- Base64 encoding functions |
2 ;; Author: wmperry | 2 ;; Author: Kyle E. Jones |
3 ;; Created: 1996/04/22 15:08:08 | 3 ;; Created: 1997/01/23 00:13:17 |
4 ;; Version: 1.7 | 4 ;; Version: 1.4 |
5 ;; Keywords: extensions | 5 ;; Keywords: extensions |
6 | 6 |
7 ;;; LCD Archive Entry: | |
8 ;;; base64.el|William M. Perry|wmperry@cs.indiana.edu| | |
9 ;;; Package for encoding/decoding base64 data (MIME)| | |
10 ;;; 1996/04/22 15:08:08|1.7|Location Undetermined | |
11 ;;; | |
12 | |
13 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
14 ;;; Copyright (c) 1996 Free Software Foundation, Inc. | 8 ;;; Copyright (C) 1997 Kyle E. Jones |
15 ;;; Copyright (c) 1995, 1996 by William M. Perry (wmperry@cs.indiana.edu) | |
16 ;;; | 9 ;;; |
17 ;;; This file is not part of GNU Emacs, but the same permissions apply. | 10 ;;; This file is not part of GNU Emacs, but the same permissions apply. |
18 ;;; | 11 ;;; |
19 ;;; GNU Emacs is free software; you can redistribute it and/or modify | 12 ;;; GNU Emacs is free software; you can redistribute it and/or modify |
20 ;;; it under the terms of the GNU General Public License as published by | 13 ;;; it under the terms of the GNU General Public License as published by |
30 ;;; along with GNU Emacs; see the file COPYING. If not, write to the | 23 ;;; along with GNU Emacs; see the file COPYING. If not, write to the |
31 ;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 24 ;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
32 ;;; Boston, MA 02111-1307, USA. | 25 ;;; Boston, MA 02111-1307, USA. |
33 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 26 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
34 | 27 |
35 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 28 ;; For non-MULE |
36 ;;; Base 64 encoding functions | 29 (if (not (fboundp 'char-int)) |
37 ;;; This code was converted to lisp code by me from the C code in | 30 (fset 'char-int 'identity)) |
38 ;;; ftp://cs.utk.edu/pub/MIME/b64encode.c | 31 |
39 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 32 (defvar base64-alphabet |
40 | 33 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/") |
41 (defvar base64-code-string | 34 |
42 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" | 35 (defvar base64-decoder-program nil |
43 "Character set used for base64 decoding") | 36 "*Non-nil value should be a string that names a MIME base64 decoder. |
44 | 37 The program should expect to read base64 data on its standard |
45 (defvar base64-decode-vector | 38 input and write the converted data to its standard output.") |
46 (let ((vec (make-vector 256 nil)) | 39 |
47 (i 0) | 40 (defvar base64-decoder-switches nil |
48 (case-fold-search nil)) | 41 "*List of command line flags passed to the command named by |
49 (while (< i 256) | 42 base64-decoder-program.") |
50 (aset vec i (string-match (regexp-quote (char-to-string i)) | 43 |
51 base64-code-string)) | 44 (defvar base64-encoder-program nil |
52 (setq i (1+ i))) | 45 "*Non-nil value should be a string that names a MIME base64 encoder. |
53 vec)) | 46 The program should expect arbitrary data on its standard |
54 | 47 input and write base64 data to its standard output.") |
55 (defvar base64-max-line-length 64) | 48 |
56 | 49 (defvar base64-encoder-switches nil |
57 ;(defun b0 (x) (aref base64-code-string (logand (lsh x -18) 63))) | 50 "*List of command line flags passed to the command named by |
58 ;(defun b1 (x) (aref base64-code-string (logand (lsh x -12) 63))) | 51 base64-encoder-program.") |
59 ;(defun b2 (x) (aref base64-code-string (logand (lsh x -6) 63))) | 52 |
60 ;(defun b3 (x) (aref base64-code-string (logand x 63))) | 53 (defconst base64-alphabet-decoding-alist |
61 | 54 '( |
62 (defmacro b0 (x) (` (aref base64-code-string (logand (lsh (, x) -18) 63)))) | 55 ( ?A . 00) ( ?B . 01) ( ?C . 02) ( ?D . 03) ( ?E . 04) ( ?F . 05) |
63 (defmacro b1 (x) (` (aref base64-code-string (logand (lsh (, x) -12) 63)))) | 56 ( ?G . 06) ( ?H . 07) ( ?I . 08) ( ?J . 09) ( ?K . 10) ( ?L . 11) |
64 (defmacro b2 (x) (` (aref base64-code-string (logand (lsh (, x) -6) 63)))) | 57 ( ?M . 12) ( ?N . 13) ( ?O . 14) ( ?P . 15) ( ?Q . 16) ( ?R . 17) |
65 (defmacro b3 (x) (` (aref base64-code-string (logand (, x) 63)))) | 58 ( ?S . 18) ( ?T . 19) ( ?U . 20) ( ?V . 21) ( ?W . 22) ( ?X . 23) |
66 | 59 ( ?Y . 24) ( ?Z . 25) ( ?a . 26) ( ?b . 27) ( ?c . 28) ( ?d . 29) |
67 (defun base64-encode (str) | 60 ( ?e . 30) ( ?f . 31) ( ?g . 32) ( ?h . 33) ( ?i . 34) ( ?j . 35) |
68 "Do base64 encoding on string STR and return the encoded string. | 61 ( ?k . 36) ( ?l . 37) ( ?m . 38) ( ?n . 39) ( ?o . 40) ( ?p . 41) |
69 This code was converted to lisp code by me from the C code in | 62 ( ?q . 42) ( ?r . 43) ( ?s . 44) ( ?t . 45) ( ?u . 46) ( ?v . 47) |
70 ftp://cs.utk.edu/pub/MIME/b64encode.c. Returns a string that is | 63 ( ?w . 48) ( ?x . 49) ( ?y . 50) ( ?z . 51) ( ?0 . 52) ( ?1 . 53) |
71 broken into `base64-max-line-length' byte lines." | 64 ( ?2 . 54) ( ?3 . 55) ( ?4 . 56) ( ?5 . 57) ( ?6 . 58) ( ?7 . 59) |
72 (or str (setq str (buffer-string))) | 65 ( ?8 . 60) ( ?9 . 61) ( ?+ . 62) ( ?/ . 63) |
73 (let ((x (base64-encode-internal str)) | 66 )) |
74 (y "")) | 67 |
75 (while (> (length x) base64-max-line-length) | 68 (defvar base64-alphabet-decoding-vector |
76 (setq y (concat y (substring x 0 base64-max-line-length) "\n") | 69 (let ((v (make-vector 123 nil)) |
77 x (substring x base64-max-line-length nil))) | 70 (p base64-alphabet-decoding-alist)) |
78 (setq y (concat y x)) | 71 (while p |
79 y)) | 72 (aset v (car (car p)) (cdr (car p))) |
80 | 73 (setq p (cdr p))) |
81 (defun base64-encode-internal (str) | 74 v)) |
82 "Do base64 encoding on string STR and return the encoded string. | 75 |
83 This code was converted to lisp code by me from the C code in | 76 (defun base64-run-command-on-region (start end output-buffer command |
84 ftp://cs.utk.edu/pub/MIME/b64encode.c. Returns the entire string, | 77 &rest arg-list) |
85 not broken up into `base64-max-line-length' byte lines." | 78 (let ((tempfile nil) status errstring) |
86 (let ( | 79 (unwind-protect |
87 (word 0) ; The word to translate | 80 (progn |
88 w1 w2 w3 | 81 (setq tempfile (make-temp-name "base64")) |
89 ) | 82 (setq status |
90 (cond | 83 (apply 'call-process-region |
91 ((> (length str) 3) | 84 start end command nil |
92 (concat | 85 (list output-buffer tempfile) |
93 (base64-encode-internal (substring str 0 3)) | 86 nil arg-list)) |
94 (base64-encode-internal (substring str 3 nil)))) | 87 (cond ((equal status 0) t) |
95 ((= (length str) 3) | 88 ((zerop (save-excursion |
96 (setq w1 (aref str 0) | 89 (set-buffer (find-file-noselect tempfile)) |
97 w2 (aref str 1) | 90 (buffer-size))) |
98 w3 (aref str 2) | 91 t) |
99 word (logior | 92 (t (save-excursion |
100 (lsh (logand w1 255) 16) | 93 (set-buffer (find-file-noselect tempfile)) |
101 (lsh (logand w2 255) 8) | 94 (setq errstring (buffer-string)) |
102 (logand w3 255))) | 95 (kill-buffer nil) |
103 (format "%c%c%c%c" (b0 word) (b1 word) (b2 word) (b3 word))) | 96 (cons status errstring))))) |
104 ((= (length str) 2) | 97 (condition-case () |
105 (setq w1 (aref str 0) | 98 (delete-file tempfile) |
106 w2 (aref str 1) | 99 (error nil))))) |
107 word (logior | 100 |
108 (lsh (logand w1 255) 16) | 101 (defun base64-insert-char (char &optional count ignored buffer) |
109 (lsh (logand w2 255) 8) | 102 (condition-case nil |
110 0)) | 103 (progn |
111 (format "%c%c%c=" (b0 word) (b1 word) (b2 word))) | 104 (insert-char char count ignored buffer) |
112 ((= (length str) 1) | 105 (fset 'vm-insert-char 'insert-char)) |
113 (setq w1 (aref str 0) | 106 (wrong-number-of-arguments |
114 word (logior | 107 (fset 'base64-insert-char 'base64-xemacs-insert-char) |
115 (lsh (logand w1 255) 16) | 108 (base64-insert-char char count ignored buffer)))) |
116 0)) | 109 |
117 (format "%c%c==" (b0 word) (b1 word))) | 110 (defun base64-xemacs-insert-char (char &optional count ignored buffer) |
118 (t "")))) | 111 (if (and buffer (eq buffer (current-buffer))) |
119 | 112 (insert-char char count) |
120 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | 113 (save-excursion |
121 ;;; Base64 decoding functions | 114 (set-buffer buffer) |
122 ;;; Most of the decoding code is courtesy Francesco Potorti` | 115 (insert-char char count)))) |
123 ;;; <F.Potorti@cnuce.cnr.it> | 116 |
124 ;;; this is much faster than my original code - thanks! | 117 (defun base64-decode-region (start end) |
125 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
126 (defun base64-decode-region (beg end) | |
127 (interactive "r") | 118 (interactive "r") |
128 (barf-if-buffer-read-only) | 119 (message "Decoding base64...") |
129 (let | 120 (let ((work-buffer nil) |
130 ((exchange (= (point) beg)) | 121 (done nil) |
131 (endchars 0) | 122 (counter 0) |
132 (list) (code)) | 123 (bits 0) |
133 (goto-char beg) | 124 (lim 0) inputpos |
134 (while (< (point) end) | 125 (non-data-chars (concat "^=" base64-alphabet))) |
135 (setq list (mapcar | 126 (unwind-protect |
136 (function | 127 (save-excursion |
137 (lambda (c) | 128 (setq work-buffer (generate-new-buffer " *base64-work*")) |
138 (cond | 129 (buffer-disable-undo work-buffer) |
139 ((aref base64-decode-vector c)) | 130 (if base64-decoder-program |
140 ((char-equal c ?=) | 131 (let* ((binary-process-output t) ; any text already has CRLFs |
141 (setq endchars (1+ endchars)) | 132 (status (apply 'command-on-region |
142 0) | 133 start end work-buffer |
143 (nil | 134 base64-decoder-program |
144 (error | 135 base64-decoder-switches))) |
145 "Character %c does not match Mime base64 coding" c))))) | 136 (if (not (eq status t)) |
146 (buffer-substring (point) (+ (point) 4)))) | 137 (error "%s" (cdr status)))) |
147 (setq code (+ (nth 3 list) (lsh (nth 2 list) 6) | 138 (goto-char start) |
148 (lsh (nth 1 list) 12) (lsh (car list) 18))) | 139 (skip-chars-forward non-data-chars end) |
149 (delete-char 4) | 140 (while (not done) |
150 (cond | 141 (setq inputpos (point)) |
151 ((zerop endchars) | 142 (cond |
152 (insert (% (lsh code -16) 256) (% (lsh code -8) 256) (% code 256))) | 143 ((> (skip-chars-forward base64-alphabet end) 0) |
153 ((= endchars 1) | 144 (setq lim (point)) |
154 (insert (% (lsh code -16) 256) (% (lsh code -8) 256)) | 145 (while (< inputpos lim) |
155 (setq end (point))) | 146 (setq bits (+ bits |
156 ((= endchars 2) | 147 (aref base64-alphabet-decoding-vector |
157 (insert (% (lsh code -16) 256)) | 148 (char-int (char-after inputpos))))) |
158 (setq end (point)))) | 149 (setq counter (1+ counter) |
159 (if (char-equal (following-char) ?\n) | 150 inputpos (1+ inputpos)) |
160 (progn (delete-char 1) | 151 (cond ((= counter 4) |
161 (setq end (- end 2))) | 152 (base64-insert-char (lsh bits -16) 1 nil work-buffer) |
162 (setq end (1- end)))) | 153 (base64-insert-char (logand (lsh bits -8) 255) 1 nil |
163 )) | 154 work-buffer) |
164 ; (if exchange | 155 (base64-insert-char (logand bits 255) 1 nil |
165 ; (exchange-point-and-mark)))) | 156 work-buffer) |
166 | 157 (setq bits 0 counter 0)) |
167 (defun base64-decode (st &optional nd) | 158 (t (setq bits (lsh bits 6))))))) |
168 "Do base64 decoding on string STR and return the original string. | 159 (cond |
169 If given buffer positions, destructively decodes that area of the | 160 ((= (point) end) |
170 current buffer." | 161 (if (not (zerop counter)) |
171 (let ((replace-p nil) | 162 (error "at least %d bits missing at end of base64 encoding" |
172 (retval nil)) | 163 (* (- 4 counter) 6))) |
173 (if (stringp st) | 164 (setq done t)) |
174 nil | 165 ((= (char-after (point)) ?=) |
175 (setq st (prog1 | 166 (setq done t) |
176 (buffer-substring st (or nd (point-max))) | 167 (cond ((= counter 1) |
177 (delete-region st (or nd (point-max)))) | 168 (error "at least 2 bits missing at end of base64 encoding")) |
178 replace-p t)) | 169 ((= counter 2) |
179 (setq retval | 170 (base64-insert-char (lsh bits -10) 1 nil work-buffer)) |
180 (save-excursion | 171 ((= counter 3) |
181 (set-buffer (get-buffer-create " *b64decode*")) | 172 (base64-insert-char (lsh bits -16) 1 nil work-buffer) |
182 (erase-buffer) | 173 (base64-insert-char (logand (lsh bits -8) 255) |
183 (insert st) | 174 1 nil work-buffer)) |
184 (goto-char (point-min)) | 175 ((= counter 0) t))) |
185 (while (re-search-forward "\r*\n" nil t) | 176 (t (skip-chars-forward non-data-chars end))))) |
186 (replace-match "")) | 177 (or (markerp end) (setq end (set-marker (make-marker) end))) |
187 (goto-char (point-min)) | 178 (goto-char start) |
188 (base64-decode-region (point-min) (point-max)) | 179 (insert-buffer-substring work-buffer) |
189 (buffer-string))) | 180 (delete-region (point) end)) |
190 (if replace-p (insert retval)) | 181 (and work-buffer (kill-buffer work-buffer)))) |
191 retval)) | 182 (message "Decoding base64... done")) |
183 | |
184 (defun base64-encode-region (start end) | |
185 (interactive "r") | |
186 (message "Encoding base64...") | |
187 (let ((work-buffer nil) | |
188 (counter 0) | |
189 (cols 0) | |
190 (bits 0) | |
191 (alphabet base64-alphabet) | |
192 inputpos) | |
193 (unwind-protect | |
194 (save-excursion | |
195 (setq work-buffer (generate-new-buffer " *base64-work*")) | |
196 (buffer-disable-undo work-buffer) | |
197 (if base64-encoder-program | |
198 (let ((status (apply 'base64-run-command-on-region | |
199 start end work-buffer | |
200 base64-encoder-program | |
201 base64-encoder-switches))) | |
202 (if (not (eq status t)) | |
203 (error "%s" (cdr status)))) | |
204 (setq inputpos start) | |
205 (while (< inputpos end) | |
206 (setq bits (+ bits (char-int (char-after inputpos)))) | |
207 (setq counter (1+ counter)) | |
208 (cond ((= counter 3) | |
209 (base64-insert-char (aref alphabet (lsh bits -18)) 1 nil | |
210 work-buffer) | |
211 (base64-insert-char | |
212 (aref alphabet (logand (lsh bits -12) 63)) | |
213 1 nil work-buffer) | |
214 (base64-insert-char | |
215 (aref alphabet (logand (lsh bits -6) 63)) | |
216 1 nil work-buffer) | |
217 (base64-insert-char | |
218 (aref alphabet (logand bits 63)) | |
219 1 nil work-buffer) | |
220 (setq cols (+ cols 4)) | |
221 (cond ((= cols 72) | |
222 (base64-insert-char ?\n 1 nil work-buffer) | |
223 (setq cols 0))) | |
224 (setq bits 0 counter 0)) | |
225 (t (setq bits (lsh bits 8)))) | |
226 (setq inputpos (1+ inputpos))) | |
227 ;; write out any remaining bits with appropriate padding | |
228 (if (= counter 0) | |
229 nil | |
230 (setq bits (lsh bits (- 16 (* 8 counter)))) | |
231 (base64-insert-char (aref alphabet (lsh bits -18)) 1 nil | |
232 work-buffer) | |
233 (base64-insert-char (aref alphabet (logand (lsh bits -12) 63)) | |
234 1 nil work-buffer) | |
235 (if (= counter 1) | |
236 (base64-insert-char ?= 2 nil work-buffer) | |
237 (base64-insert-char (aref alphabet (logand (lsh bits -6) 63)) | |
238 1 nil work-buffer) | |
239 (base64-insert-char ?= 1 nil work-buffer))) | |
240 (if (> cols 0) | |
241 (base64-insert-char ?\n 1 nil work-buffer))) | |
242 (or (markerp end) (setq end (set-marker (make-marker) end))) | |
243 (goto-char start) | |
244 (insert-buffer-substring work-buffer) | |
245 (delete-region (point) end)) | |
246 (and work-buffer (kill-buffer work-buffer)))) | |
247 (message "Encoding base64... done")) | |
248 | |
249 (defun base64-encode (string) | |
250 (save-excursion | |
251 (set-buffer (get-buffer-create " *base64-encode*")) | |
252 (erase-buffer) | |
253 (insert string) | |
254 (base64-encode-region (point-min) (point-max)) | |
255 (skip-chars-backward " \t\r\n") | |
256 (delete-region (point-max) (point)) | |
257 (prog1 | |
258 (buffer-string) | |
259 (kill-buffer (current-buffer))))) | |
260 | |
261 (defun base64-decode (string) | |
262 (save-excursion | |
263 (set-buffer (get-buffer-create " *base64-decode*")) | |
264 (erase-buffer) | |
265 (insert string) | |
266 (base64-decode-region (point-min) (point-max)) | |
267 (goto-char (point-max)) | |
268 (skip-chars-backward " \t\r\n") | |
269 (delete-region (point-max) (point)) | |
270 (prog1 | |
271 (buffer-string) | |
272 (kill-buffer (current-buffer))))) | |
192 | 273 |
193 (provide 'base64) | 274 (provide 'base64) |