2 ;;; mel-b.el: Base64 encoder/decoder for GNU Emacs
4 ;;; Copyright (C) 1995 Free Software Foundation, Inc.
5 ;;; Copyright (C) 1995,1996 MORIOKA Tomohiko
7 ;;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
8 ;;; Maintainer: MORIOKA Tomohiko <morioka@jaist.ac.jp>
11 ;;; $Id: mel-b.el,v 3.2 1996/01/09 18:25:22 morioka Exp $
12 ;;; Keywords: MIME, Base64
14 ;;; This file is part of MEL (MIME Encoding Library).
16 ;;; This program is free software; you can redistribute it and/or
17 ;;; modify it under the terms of the GNU General Public License as
18 ;;; published by the Free Software Foundation; either version 2, or
19 ;;; (at your option) any later version.
21 ;;; This program is distributed in the hope that it will be useful,
22 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
23 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 ;;; General Public License for more details.
26 ;;; You should have received a copy of the GNU General Public License
27 ;;; along with This program. If not, write to the Free Software
28 ;;; Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
36 (defvar base64-external-encoder '("mmencode")
37 "*list of base64 encoder program name and its arguments.")
39 (defvar base64-external-decoder '("mmencode" "-u")
40 "*list of base64 decoder program name and its arguments.")
42 (defvar base64-internal-encoding-limit 1000
43 "*limit size to use internal base64 encoder.
44 If size of input to encode is larger than this limit,
45 external encoder is called.")
47 (defvar base64-internal-decoding-limit 1000
48 "*limit size to use internal base64 decoder.
49 If size of input to decode is larger than this limit,
50 external decoder is called.")
53 ;;; @ internal base64 decoder/encoder
54 ;;; based on base64 decoder by Enami Tsugutomo
56 ;;; @@ convert from/to base64 char
59 (defun base64-num-to-char (n)
62 ((< n 52) (+ ?a (- n 26)))
63 ((< n 62) (+ ?0 (- n 52)))
66 (t (error "not a base64 integer %d" n))))
68 (defun base64-char-to-num (c)
69 (cond ((and (<= ?A c) (<= c ?Z)) (- c ?A))
70 ((and (<= ?a c) (<= c ?z)) (+ (- c ?a) 26))
71 ((and (<= ?0 c) (<= c ?9)) (+ (- c ?0) 52))
75 (t (error "not a base64 character %c" c))))
78 ;;; @@ encode/decode one base64 unit
81 (defun base64-mask (i n) (logand i (1- (ash 1 n))))
83 (defun base64-encode-1 (a &optional b &optional c)
85 (cons (logior (ash (base64-mask a 2) (- 6 2))
88 (cons (logior (ash (base64-mask b 4) (- 6 4))
91 (cons (base64-mask c (- 6 0))
94 (defun base64-decode-1 (a b &optional c &optional d)
95 (cons (logior (ash a 2) (ash b (- 2 6)))
96 (if c (cons (logior (ash (base64-mask b 4) 4)
97 (base64-mask (ash c (- 4 6)) 4))
98 (if d (cons (logior (ash (base64-mask c 2) 6) d)
101 (defun base64-encode-chars (a &optional b &optional c)
102 (mapcar (function base64-num-to-char) (base64-encode-1 a b c)))
104 (defun base64-decode-chars (&rest args)
105 (apply (function base64-decode-1)
106 (mapcar (function base64-char-to-num) args)
110 ;;; @@ encode/decode base64 string
113 (defun base64-encode-string (string)
114 (let ((len (length string))
123 (mapconcat (function char-to-string)
124 (apply (function base64-encode-chars) pack)
127 (pack-sequence (substring string b e) 3)
134 (let* ((es (mapconcat
137 (mapconcat (function char-to-string)
138 (apply (function base64-encode-chars) pack)
141 (pack-sequence (substring string b) 3)
143 (m (mod (length es) 4))
145 (concat dest es (cond ((= m 3) "=")
150 (defun base64-decode-string (string)
153 (mapconcat (function char-to-string)
154 (apply (function base64-decode-chars) pack)
157 (pack-sequence string 4)
161 ;;; @ encode/decode base64 region
164 (defun base64-internal-encode-region (beg end)
167 (narrow-to-region beg end)
168 (let ((str (buffer-substring beg end)))
169 (delete-region beg end)
170 (insert (base64-encode-string str))
177 (defun base64-internal-decode-region (beg end)
180 (narrow-to-region beg end)
181 (goto-char (point-min))
182 (while (search-forward "\n" nil t)
185 (let ((str (buffer-substring (point-min)(point-max))))
186 (delete-region (point-min)(point-max))
187 (insert (base64-decode-string str))
190 (cond ((boundp 'MULE)
191 (define-program-coding-system
192 nil (car base64-external-encoder) *noconv*)
193 (define-program-coding-system
194 nil (car base64-external-decoder) *noconv*)
197 (define-program-kanji-code
198 nil (car base64-external-encoder) 0)
199 (define-program-kanji-code
200 nil (car base64-external-decoder) 0)
203 (defun base64-external-encode-region (beg end)
206 (narrow-to-region beg end)
207 (let ((selective-display nil) ;Disable ^M to nl translation.
209 (kanji-flag nil)) ;NEmacs
210 (apply (function call-process-region)
211 beg end (car base64-external-encoder)
212 t t nil (cdr base64-external-encoder))
215 ;; regularize line break code
216 (goto-char (point-min))
217 (while (re-search-forward "\r$" nil t)
222 (defun base64-external-decode-region (beg end)
224 (let ((selective-display nil) ;Disable ^M to nl translation.
226 (kanji-flag nil)) ;NEmacs
227 (apply (function call-process-region)
228 beg end (car base64-external-decoder)
229 t t nil (cdr base64-external-decoder))
232 (defun base64-encode-region (beg end)
234 (if (and base64-internal-encoding-limit
235 (> (- end beg) base64-internal-encoding-limit))
236 (base64-external-encode-region beg end)
237 (base64-internal-encode-region beg end)
240 (defun base64-decode-region (beg end)
242 (if (and base64-internal-decoding-limit
243 (> (- end beg) base64-internal-decoding-limit))
244 (base64-external-decode-region beg end)
245 (base64-internal-decode-region beg end)
252 (defun base64-encoded-length (string)
253 (let ((len (length string)))
255 (if (= (mod len 3) 0) 0 1)
259 (defun pack-sequence (seq size)
260 "Split sequence SEQ into SIZE elements packs,
261 and return list of packs. [mel-b; tl-seq function]"
262 (let ((len (length seq)) (p 0) obj
266 (setq obj (elt seq p))
267 (setq unit (cons obj unit))
271 (setq dest (cons (reverse unit) dest))
278 (setq dest (cons (reverse unit) dest))