1 ;;; mel.el : a MIME encoding/decoding library
3 ;; Copyright (C) 1995,1996,1997,1998 Free Software Foundation, Inc.
5 ;; Author: MORIOKA Tomohiko <morioka@jaist.ac.jp>
6 ;; modified by Shuhei KOBAYASHI <shuhei-k@jaist.ac.jp>
8 ;; Keywords: MIME, Base64, Quoted-Printable, uuencode, gzip64
10 ;; This file is part of MEL (MIME Encoding Library).
12 ;; This program is free software; you can redistribute it and/or
13 ;; modify it under the terms of the GNU General Public License as
14 ;; published by the Free Software Foundation; either version 2, or (at
15 ;; your option) any later version.
17 ;; This program is distributed in the hope that it will be useful, but
18 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 ;; 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.
35 (defvar base64-internal-encoding-limit 1000
36 "*limit size to use internal base64 encoder.
37 If size of input to encode is larger than this limit,
38 external encoder is called.")
40 (defvar base64-internal-decoding-limit 1000
41 "*limit size to use internal base64 decoder.
42 size of input to decode is larger than this limit,
43 external decoder is called.")
45 (defvar quoted-printable-internal-encoding-limit
46 (if (and (featurep 'xemacs)(featurep 'mule))
49 (if (exec-installed-p "mmencode")
51 (message "Don't found external encoder for Quoted-Printable!")
53 "*limit size to use internal quoted-printable encoder.
54 If size of input to encode is larger than this limit,
55 external encoder is called.")
57 (defvar quoted-printable-internal-decoding-limit nil
58 "*limit size to use internal quoted-printable decoder.
59 If size of input to decode is larger than this limit,
60 external decoder is called.")
67 (defvar base64-dl-module
68 (and (fboundp 'dynamic-link)
69 (let ((path (expand-file-name "base64.so" exec-directory)))
70 (and (file-exists-p path)
73 (when base64-dl-module
74 (autoload 'base64-dl-encode-string "mel-dl"
75 "Encode STRING to base64, and return the result.")
76 (autoload 'base64-dl-decode-string "mel-dl"
77 "Decode STRING which is encoded in base64, and return the result.")
78 (autoload 'base64-dl-encode-region "mel-dl"
79 "Encode current region by base64." t)
80 (autoload 'base64-dl-decode-region "mel-dl"
81 "Decode current region by base64." t))
84 (autoload 'base64-internal-encode-string "mel-b"
85 "Encode STRING to base64, and return the result.")
86 (autoload 'base64-internal-decode-string "mel-b"
87 "Decode STRING which is encoded in base64, and return the result.")
88 (autoload 'base64-internal-encode-region "mel-b"
89 "Encode current region by base64." t)
90 (autoload 'base64-internal-decode-region "mel-b"
91 "Decode current region by base64." t)
92 (autoload 'base64-internal-insert-encoded-file "mel-b"
93 "Encode contents of file to base64, and insert the result." t)
94 (autoload 'base64-internal-write-decoded-region "mel-b"
95 "Decode and write current region encoded by base64 into FILENAME." t)
97 (autoload 'base64-external-encode-string "mel-b"
98 "Encode STRING to base64, and return the result.")
99 (autoload 'base64-external-decode-string "mel-b"
100 "Decode STRING which is encoded in base64, and return the result.")
101 (autoload 'base64-external-encode-region "mel-b"
102 "Encode current region by base64." t)
103 (autoload 'base64-external-decode-region "mel-b"
104 "Decode current region by base64." t)
105 (autoload 'base64-external-insert-encoded-file "mel-b"
106 "Encode contents of file to base64, and insert the result." t)
107 (autoload 'base64-external-write-decoded-region "mel-b"
108 "Decode and write current region encoded by base64 into FILENAME." t)
111 (autoload 'base64-internal-encoded-length "mel-b")
114 (autoload 'quoted-printable-internal-encode-string "mel-q"
115 "Encode STRING to quoted-printable, and return the result.")
116 (autoload 'quoted-printable-internal-decode-string "mel-q"
117 "Decode STRING which is encoded in quoted-printable, and return the result.")
118 (autoload 'quoted-printable-internal-encode-region "mel-q"
119 "Encode current region by Quoted-Printable." t)
120 (autoload 'quoted-printable-internal-decode-region "mel-q"
121 "Decode current region by Quoted-Printable." t)
123 (autoload 'quoted-printable-external-encode-string "mel-q"
124 "Encode STRING to quoted-printable, and return the result.")
125 (autoload 'quoted-printable-external-decode-string "mel-q"
126 "Decode STRING which is encoded in quoted-printable, and return the result.")
127 (autoload 'quoted-printable-external-encode-region "mel-q"
128 "Encode current region by Quoted-Printable." t)
129 (autoload 'quoted-printable-external-decode-region "mel-q"
130 "Decode current region by Quoted-Printable." t)
132 (autoload 'quoted-printable-external-insert-encoded-file "mel-q"
133 "Encode contents of file to quoted-printable, and insert the result." t)
134 (autoload 'quoted-printable-external-write-decoded-region "mel-q"
135 "Decode and write current region encoded by quoted-printable into FILENAME."
139 (autoload 'q-encoding-internal-encode-string "mel-q"
140 "Encode STRING to Q-encoding of encoded-word, and return the result.")
141 (autoload 'q-encoding-internal-decode-string "mel-q"
142 "Decode STRING which is encoded in Q-encoding and return the result.")
143 (autoload 'q-encoding-internal-encoded-length "mel-q")
146 (autoload 'uuencode-external-encode-region "mel-u"
147 "Encode current region by unofficial uuencode format." t)
148 (autoload 'uuencode-external-decode-region "mel-u"
149 "Decode current region by unofficial uuencode format." t)
150 (autoload 'uuencode-external-insert-encoded-file "mel-u"
151 "Insert file encoded by unofficial uuencode format." t)
152 (autoload 'uuencode-external-write-decoded-region "mel-u"
153 "Decode and write current region encoded by uuencode into FILENAME." t)
156 (autoload 'gzip64-external-encode-region "mel-g"
157 "Encode current region by unofficial x-gzip64 format." t)
158 (autoload 'gzip64-external-decode-region "mel-g"
159 "Decode current region by unofficial x-gzip64 format." t)
160 (autoload 'gzip64-external-insert-encoded-file "mel-g"
161 "Insert file encoded by unofficial gzip64 format." t)
162 (autoload 'gzip64-external-write-decoded-region "mel-g"
163 "Decode and write current region encoded by gzip64 into FILENAME." t)
166 (when (fboundp 'make-ccl-coding-system)
167 (unless (and (boundp 'ccl-encoder-eof-block-is-broken)
168 ccl-encoder-eof-block-is-broken)
169 (autoload 'base64-ccl-encode-string "mel-ccl"
170 "Encode STRING with base64 encoding.")
171 (autoload 'base64-ccl-encode-region "mel-ccl"
172 "Encode region from START to END with base64 encoding." t)
173 (autoload 'base64-ccl-insert-encoded-file "mel-ccl"
174 "Encode contents of file FILENAME to base64, and insert the result." t))
176 (autoload 'base64-ccl-decode-string "mel-ccl"
177 "Decode base64 encoded STRING")
178 (autoload 'base64-ccl-decode-region "mel-ccl"
179 "Decode base64 encoded STRING" t)
180 (autoload 'base64-ccl-write-decoded-region "mel-ccl"
181 "Decode the region from START to END and write out to FILENAME." t)
183 (unless (and (boundp 'ccl-encoder-eof-block-is-broken)
184 ccl-encoder-eof-block-is-broken)
185 (autoload 'quoted-printable-ccl-encode-string "mel-ccl"
186 "Encode STRING with quoted-printable encoding.")
187 (autoload 'quoted-printable-ccl-encode-region "mel-ccl"
188 "Encode the region from START to END with quoted-printable
190 (autoload 'quoted-printable-ccl-insert-encoded-file "mel-ccl"
191 "Encode contents of the file named as FILENAME, and insert it." t))
193 (autoload 'quoted-printable-ccl-decode-string "mel-ccl"
194 "Decode quoted-printable encoded STRING.")
195 (autoload 'quoted-printable-ccl-decode-region "mel-ccl"
196 "Decode the region from START to END with quoted-printable
198 (autoload 'quoted-printable-ccl-write-decoded-region "mel-ccl"
199 "Decode quoted-printable encoded current region and write out to FILENAME." t)
201 (autoload 'q-encoding-ccl-encode-string "mel-ccl"
202 "Encode STRING to Q-encoding of encoded-word, and return the result.
203 MODE allows `text', `comment', `phrase' or nil. Default value is
205 (autoload 'q-encoding-ccl-decode-string "mel-ccl"
206 "Decode Q encoded STRING and return the result.")
209 ;;; @ entrance functions.
213 ((fboundp 'base64-dl-encode-string)
214 (defalias 'base64-encode-string 'base64-dl-encode-string))
215 ((fboundp 'base64-ccl-encode-string)
216 (defalias 'base64-encode-string 'base64-ccl-encode-string))
218 (defalias 'base64-encode-string 'base64-internal-encode-string)))
220 (defun base64-internal-external-decode-string (string)
221 "Decode STRING which is encoded in base64, and return the result.
222 This function calls internal base64 decoder if size of STRING is
223 smaller than `base64-internal-decoding-limit', otherwise it calls
224 external base64 decoder specified by `base64-external-decoder'. In
225 this case, you must install the program (maybe mmencode included in
226 metamail or XEmacs package)."
228 (if (and base64-internal-decoding-limit
229 (> (length string) base64-internal-decoding-limit))
230 (base64-external-decode-string string)
231 (base64-internal-decode-string string)))
234 ((fboundp 'base64-dl-decode-string)
235 (defalias 'base64-decode-string 'base64-dl-decode-string))
236 ((fboundp 'base64-ccl-decode-string)
237 (defalias 'base64-decode-string 'base64-ccl-decode-string))
239 (defalias 'base64-decode-string 'base64-internal-external-decode-string)))
241 (defun base64-internal-external-encode-region (start end)
242 "Encode current region by base64.
243 START and END are buffer positions.
244 This function calls internal base64 encoder if size of region is
245 smaller than `base64-internal-encoding-limit', otherwise it calls
246 external base64 encoder specified by `base64-external-encoder'. In
247 this case, you must install the program (maybe mmencode included in
248 metamail or XEmacs package)."
250 (if (and base64-internal-encoding-limit
251 (> (- end start) base64-internal-encoding-limit))
252 (base64-external-encode-region start end)
253 (base64-internal-encode-region start end)))
256 ((fboundp 'base64-dl-encode-region)
257 (defalias 'base64-encode-region 'base64-dl-encode-region)) ; no fold
258 ((fboundp 'base64-ccl-encode-region)
259 (defalias 'base64-encode-region 'base64-ccl-encode-region)) ; no fold
261 (defalias 'base64-encode-region 'base64-internal-external-encode-region))) ; LF fold
263 (defun base64-internal-external-decode-region (start end)
264 "Decode current region by base64.
265 START and END are buffer positions.
266 This function calls internal base64 decoder if size of region is
267 smaller than `base64-internal-decoding-limit', otherwise it calls
268 external base64 decoder specified by `base64-external-decoder'. In
269 this case, you must install the program (maybe mmencode included in
270 metamail or XEmacs package)."
272 (if (and base64-internal-decoding-limit
273 (> (- end start) base64-internal-decoding-limit))
274 (base64-external-decode-region start end)
275 (base64-internal-decode-region start end)))
278 ((fboundp 'base64-dl-decode-region)
279 (defalias 'base64-decode-region 'base64-dl-decode-region))
280 ((fboundp 'base64-ccl-decode-region)
281 (defalias 'base64-decode-region 'base64-ccl-decode-region))
283 (defalias 'base64-decode-region 'base64-internal-external-decode-region)))
285 (defun base64-internal-external-insert-encoded-file (filename)
286 "Encode contents of file FILENAME to base64, and insert the result.
287 It calls external base64 encoder specified by
288 `base64-external-encoder'. So you must install the program (maybe
289 mmencode included in metamail or XEmacs package)."
290 (interactive (list (read-file-name "Insert encoded file: ")))
291 (if (and base64-internal-encoding-limit
292 (> (nth 7 (file-attributes filename))
293 base64-internal-encoding-limit))
294 (base64-external-insert-encoded-file filename)
295 (base64-internal-insert-encoded-file filename)))
298 ((fboundp 'base64-ccl-insert-encoded-file)
299 (defalias 'base64-insert-encoded-file 'base64-ccl-insert-encoded-file))
301 (defalias 'base64-insert-encoded-file 'base64-internal-external-insert-encoded-file)))
303 (defun base64-internal-external-write-decoded-region (start end filename)
304 "Decode and write current region encoded by base64 into FILENAME.
305 START and END are buffer positions."
307 (list (region-beginning) (region-end)
308 (read-file-name "Write decoded region to file: ")))
309 (if (and base64-internal-decoding-limit
310 (> (- end start) base64-internal-decoding-limit))
311 (base64-external-write-decoded-region start end filename)
312 (base64-internal-write-decoded-region start end filename)))
315 ((fboundp 'base64-ccl-write-decoded-region)
316 (defalias 'base64-write-decoded-region 'base64-ccl-write-decoded-region))
318 (defalias 'base64-write-decoded-region 'base64-internal-external-write-decoded-region)))
322 (defalias 'base64-encoded-length 'base64-internal-encoded-length)))
325 ((fboundp 'quoted-printable-ccl-encode-string)
326 (defalias 'quoted-printable-encode-string 'quoted-printable-ccl-encode-string))
328 (defun quoted-printable-encode-string (string)
329 "Encode STRING to quoted-printable, and return the result."
330 (if (and quoted-printable-internal-encoding-limit
331 (> (length string) quoted-printable-internal-encoding-limit))
332 (quoted-printable-external-encode-string string)
333 (quoted-printable-internal-encode-string string)))))
336 ((fboundp 'quoted-printable-ccl-decode-string)
337 (defalias 'quoted-printable-decode-string 'quoted-printable-ccl-decode-string))
339 (defun quoted-printable-decode-string (string)
340 "Decode STRING which is encoded in quoted-printable, and return the result."
341 (if (and quoted-printable-internal-decoding-limit
342 (> (length string) quoted-printable-internal-decoding-limit))
343 (quoted-printable-external-decode-string string)
344 (quoted-printable-internal-decode-string string)))))
347 ((fboundp 'quoted-printable-ccl-encode-region)
348 (defalias 'quoted-printable-encode-region 'quoted-printable-ccl-encode-region))
350 (defun quoted-printable-encode-region (start end)
351 "Encode current region by quoted-printable.
352 START and END are buffer positions.
353 This function calls internal quoted-printable encoder if size of
354 region is smaller than `quoted-printable-internal-encoding-limit',
355 otherwise it calls external quoted-printable encoder specified by
356 `quoted-printable-external-encoder'. In this case, you must install
357 the program (maybe mmencode included in metamail or XEmacs package)."
359 (if (and quoted-printable-internal-encoding-limit
360 (> (- end start) quoted-printable-internal-encoding-limit))
361 (quoted-printable-external-encode-region start end)
362 (quoted-printable-internal-encode-region start end)
366 ((fboundp 'quoted-printable-ccl-decode-region)
367 (defalias 'quoted-printable-decode-region 'quoted-printable-ccl-decode-region))
369 (defun quoted-printable-decode-region (start end)
370 "Decode current region by quoted-printable.
371 START and END are buffer positions.
372 This function calls internal quoted-printable decoder if size of
373 region is smaller than `quoted-printable-internal-decoding-limit',
374 otherwise it calls external quoted-printable decoder specified by
375 `quoted-printable-external-decoder'. In this case, you must install
376 the program (maybe mmencode included in metamail or XEmacs package)."
378 (if (and quoted-printable-internal-decoding-limit
379 (> (- end start) quoted-printable-internal-decoding-limit))
380 (quoted-printable-external-decode-region start end)
381 (quoted-printable-internal-decode-region start end)
385 ((fboundp 'quoted-printable-ccl-insert-encoded-file)
386 (defalias 'quoted-printable-insert-encoded-file 'quoted-printable-ccl-insert-encoded-file))
388 (defalias 'quoted-printable-insert-encoded-file 'quoted-printable-external-insert-encoded-file)))
391 ((fboundp 'quoted-printable-ccl-write-decoded-region)
392 (defalias 'quoted-printable-write-decoded-region 'quoted-printable-ccl-write-decoded-region))
394 (defalias 'quoted-printable-write-decoded-region 'quoted-printable-external-write-decoded-region)))
397 ((fboundp 'q-encoding-ccl-encode-string)
398 (defalias 'q-encoding-encode-string 'q-encoding-ccl-encode-string))
400 (defalias 'q-encoding-encode-string 'q-encoding-internal-encode-string)))
403 ((fboundp 'q-encoding-ccl-decode-string)
404 (defalias 'q-encoding-decode-string 'q-encoding-ccl-decode-string))
406 (defalias 'q-encoding-decode-string 'q-encoding-internal-decode-string)))
410 (defalias 'q-encoding-encoded-length 'q-encoding-internal-encoded-length)))
414 (defalias 'uuencode-encode-region 'uuencode-external-encode-region)))
418 (defalias 'uuencode-decode-region 'uuencode-external-decode-region)))
422 (defalias 'uuencode-insert-encoded-file 'uuencode-external-insert-encoded-file)))
426 (defalias 'uuencode-write-decoded-region 'uuencode-external-write-decoded-region)))
430 (defalias 'gzip64-encode-region 'gzip64-external-encode-region)))
434 (defalias 'gzip64-decode-region 'gzip64-external-decode-region)))
438 (defalias 'gzip64-insert-encoded-file 'gzip64-external-insert-encoded-file)))
442 (defalias 'gzip64-write-decoded-region 'gzip64-external-write-decoded-region)))
448 (defvar mime-encoding-method-alist
449 '(("base64" . base64-encode-region)
450 ("quoted-printable" . quoted-printable-encode-region)
451 ;; Not standard, their use is DISCOURAGED.
452 ;; ("x-uue" . uuencode-encode-region)
453 ;; ("x-gzip64" . gzip64-encode-region)
458 "Alist of encoding vs. corresponding method to encode region.
459 Each element looks like (STRING . FUNCTION) or (STRING . nil).
460 STRING is content-transfer-encoding.
461 FUNCTION is region encoder and nil means not to encode.")
464 (defvar mime-decoding-method-alist
465 '(("base64" . base64-decode-region)
466 ("quoted-printable" . quoted-printable-decode-region)
467 ("x-uue" . uuencode-decode-region)
468 ("x-uuencode" . uuencode-decode-region)
469 ("x-gzip64" . gzip64-decode-region)
471 "Alist of encoding vs. corresponding method to decode region.
472 Each element looks like (STRING . FUNCTION).
473 STRING is content-transfer-encoding.
474 FUNCTION is region decoder.")
477 (defun mime-encode-region (start end encoding)
478 "Encode region START to END of current buffer using ENCODING.
479 ENCODING must be string. If ENCODING is found in
480 `mime-encoding-method-alist' as its key, this function encodes the
481 region by its value."
483 (list (region-beginning) (region-end)
484 (completing-read "encoding: "
485 mime-encoding-method-alist
488 (let ((f (cdr (assoc encoding mime-encoding-method-alist))))
490 (funcall f start end)
494 (defun mime-decode-region (start end encoding)
495 "Decode region START to END of current buffer using ENCODING.
496 ENCODING must be string. If ENCODING is found in
497 `mime-decoding-method-alist' as its key, this function decodes the
498 region by its value."
500 (list (region-beginning) (region-end)
501 (completing-read "encoding: "
502 mime-decoding-method-alist
505 (let ((f (cdr (assoc encoding mime-decoding-method-alist))))
507 (funcall f start end)
515 (defvar mime-string-decoding-method-alist
516 '(("base64" . base64-decode-string)
517 ("quoted-printable" . quoted-printable-decode-string)
520 ("binary" . identity)
522 "Alist of encoding vs. corresponding method to decode string.
523 Each element looks like (STRING . FUNCTION).
524 STRING is content-transfer-encoding.
525 FUNCTION is string decoder.")
528 (defun mime-decode-string (string encoding)
529 "Decode STRING using ENCODING.
530 ENCODING must be string. If ENCODING is found in
531 `mime-string-decoding-method-alist' as its key, this function decodes
532 the STRING by its value."
533 (let ((f (cdr (assoc encoding mime-string-decoding-method-alist))))
538 (mime-decode-region (point-min)(point-max) encoding)
547 (defvar mime-file-encoding-method-alist
548 '(("base64" . base64-insert-encoded-file)
549 ("quoted-printable" . quoted-printable-insert-encoded-file)
550 ;; Not standard, their use is DISCOURAGED.
551 ;; ("x-uue" . uuencode-insert-encoded-file)
552 ;; ("x-gzip64" . gzip64-insert-encoded-file)
553 ("7bit" . insert-file-contents-as-binary)
554 ("8bit" . insert-file-contents-as-binary)
555 ("binary" . insert-file-contents-as-binary)
557 "Alist of encoding vs. corresponding method to insert encoded file.
558 Each element looks like (STRING . FUNCTION).
559 STRING is content-transfer-encoding.
560 FUNCTION is function to insert encoded file.")
563 (defvar mime-file-decoding-method-alist
564 '(("base64" . base64-write-decoded-region)
565 ("quoted-printable" . quoted-printable-write-decoded-region)
566 ("x-uue" . uuencode-write-decoded-region)
567 ("x-gzip64" . gzip64-write-decoded-region)
568 ("7bit" . write-region-as-binary)
569 ("8bit" . write-region-as-binary)
570 ("binary" . write-region-as-binary)
572 "Alist of encoding vs. corresponding method to write decoded region to file.
573 Each element looks like (STRING . FUNCTION).
574 STRING is content-transfer-encoding.
575 FUNCTION is function to write decoded region to file.")
578 (defun mime-insert-encoded-file (filename encoding)
579 "Insert file FILENAME encoded by ENCODING format."
581 (list (read-file-name "Insert encoded file: ")
582 (completing-read "encoding: "
583 mime-encoding-method-alist
586 (let ((f (cdr (assoc encoding mime-file-encoding-method-alist))))
592 (defun mime-write-decoded-region (start end filename encoding)
593 "Decode and write current region encoded by ENCODING into FILENAME.
594 START and END are buffer positions."
596 (list (region-beginning) (region-end)
597 (read-file-name "Write decoded region to file: ")
598 (completing-read "encoding: "
599 mime-file-decoding-method-alist
601 (let ((f (cdr (assoc encoding mime-file-decoding-method-alist))))
603 (funcall f start end filename)
612 ;;; mel.el ends here.