Mercurial > hg > xemacs-beta
diff lisp/w3/base64.el @ 16:0293115a14e9 r19-15b91
Import from CVS: tag r19-15b91
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:49:20 +0200 |
parents | 9ee227acff29 |
children | e04119814345 |
line wrap: on
line diff
--- a/lisp/w3/base64.el Mon Aug 13 08:48:43 2007 +0200 +++ b/lisp/w3/base64.el Mon Aug 13 08:49:20 2007 +0200 @@ -1,18 +1,11 @@ ;;; base64.el,v --- Base64 encoding functions -;; Author: wmperry -;; Created: 1996/04/22 15:08:08 -;; Version: 1.7 +;; Author: Kyle E. Jones +;; Created: 1997/01/23 00:13:17 +;; Version: 1.4 ;; Keywords: extensions -;;; LCD Archive Entry: -;;; base64.el|William M. Perry|wmperry@cs.indiana.edu| -;;; Package for encoding/decoding base64 data (MIME)| -;;; 1996/04/22 15:08:08|1.7|Location Undetermined -;;; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Copyright (c) 1996 Free Software Foundation, Inc. -;;; Copyright (c) 1995, 1996 by William M. Perry (wmperry@cs.indiana.edu) +;;; Copyright (C) 1997 Kyle E. Jones ;;; ;;; This file is not part of GNU Emacs, but the same permissions apply. ;;; @@ -32,162 +25,250 @@ ;;; Boston, MA 02111-1307, USA. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Base 64 encoding functions -;;; This code was converted to lisp code by me from the C code in -;;; ftp://cs.utk.edu/pub/MIME/b64encode.c -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; For non-MULE +(if (not (fboundp 'char-int)) + (fset 'char-int 'identity)) + +(defvar base64-alphabet + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/") -(defvar base64-code-string - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" - "Character set used for base64 decoding") +(defvar base64-decoder-program nil + "*Non-nil value should be a string that names a MIME base64 decoder. +The program should expect to read base64 data on its standard +input and write the converted data to its standard output.") + +(defvar base64-decoder-switches nil + "*List of command line flags passed to the command named by +base64-decoder-program.") -(defvar base64-decode-vector - (let ((vec (make-vector 256 nil)) - (i 0) - (case-fold-search nil)) - (while (< i 256) - (aset vec i (string-match (regexp-quote (char-to-string i)) - base64-code-string)) - (setq i (1+ i))) - vec)) +(defvar base64-encoder-program nil + "*Non-nil value should be a string that names a MIME base64 encoder. +The program should expect arbitrary data on its standard +input and write base64 data to its standard output.") + +(defvar base64-encoder-switches nil + "*List of command line flags passed to the command named by +base64-encoder-program.") -(defvar base64-max-line-length 64) +(defconst base64-alphabet-decoding-alist + '( + ( ?A . 00) ( ?B . 01) ( ?C . 02) ( ?D . 03) ( ?E . 04) ( ?F . 05) + ( ?G . 06) ( ?H . 07) ( ?I . 08) ( ?J . 09) ( ?K . 10) ( ?L . 11) + ( ?M . 12) ( ?N . 13) ( ?O . 14) ( ?P . 15) ( ?Q . 16) ( ?R . 17) + ( ?S . 18) ( ?T . 19) ( ?U . 20) ( ?V . 21) ( ?W . 22) ( ?X . 23) + ( ?Y . 24) ( ?Z . 25) ( ?a . 26) ( ?b . 27) ( ?c . 28) ( ?d . 29) + ( ?e . 30) ( ?f . 31) ( ?g . 32) ( ?h . 33) ( ?i . 34) ( ?j . 35) + ( ?k . 36) ( ?l . 37) ( ?m . 38) ( ?n . 39) ( ?o . 40) ( ?p . 41) + ( ?q . 42) ( ?r . 43) ( ?s . 44) ( ?t . 45) ( ?u . 46) ( ?v . 47) + ( ?w . 48) ( ?x . 49) ( ?y . 50) ( ?z . 51) ( ?0 . 52) ( ?1 . 53) + ( ?2 . 54) ( ?3 . 55) ( ?4 . 56) ( ?5 . 57) ( ?6 . 58) ( ?7 . 59) + ( ?8 . 60) ( ?9 . 61) ( ?+ . 62) ( ?/ . 63) + )) -;(defun b0 (x) (aref base64-code-string (logand (lsh x -18) 63))) -;(defun b1 (x) (aref base64-code-string (logand (lsh x -12) 63))) -;(defun b2 (x) (aref base64-code-string (logand (lsh x -6) 63))) -;(defun b3 (x) (aref base64-code-string (logand x 63))) - -(defmacro b0 (x) (` (aref base64-code-string (logand (lsh (, x) -18) 63)))) -(defmacro b1 (x) (` (aref base64-code-string (logand (lsh (, x) -12) 63)))) -(defmacro b2 (x) (` (aref base64-code-string (logand (lsh (, x) -6) 63)))) -(defmacro b3 (x) (` (aref base64-code-string (logand (, x) 63)))) +(defvar base64-alphabet-decoding-vector + (let ((v (make-vector 123 nil)) + (p base64-alphabet-decoding-alist)) + (while p + (aset v (car (car p)) (cdr (car p))) + (setq p (cdr p))) + v)) -(defun base64-encode (str) - "Do base64 encoding on string STR and return the encoded string. -This code was converted to lisp code by me from the C code in -ftp://cs.utk.edu/pub/MIME/b64encode.c. Returns a string that is -broken into `base64-max-line-length' byte lines." - (or str (setq str (buffer-string))) - (let ((x (base64-encode-internal str)) - (y "")) - (while (> (length x) base64-max-line-length) - (setq y (concat y (substring x 0 base64-max-line-length) "\n") - x (substring x base64-max-line-length nil))) - (setq y (concat y x)) - y)) +(defun base64-run-command-on-region (start end output-buffer command + &rest arg-list) + (let ((tempfile nil) status errstring) + (unwind-protect + (progn + (setq tempfile (make-temp-name "base64")) + (setq status + (apply 'call-process-region + start end command nil + (list output-buffer tempfile) + nil arg-list)) + (cond ((equal status 0) t) + ((zerop (save-excursion + (set-buffer (find-file-noselect tempfile)) + (buffer-size))) + t) + (t (save-excursion + (set-buffer (find-file-noselect tempfile)) + (setq errstring (buffer-string)) + (kill-buffer nil) + (cons status errstring))))) + (condition-case () + (delete-file tempfile) + (error nil))))) + +(defun base64-insert-char (char &optional count ignored buffer) + (condition-case nil + (progn + (insert-char char count ignored buffer) + (fset 'vm-insert-char 'insert-char)) + (wrong-number-of-arguments + (fset 'base64-insert-char 'base64-xemacs-insert-char) + (base64-insert-char char count ignored buffer)))) + +(defun base64-xemacs-insert-char (char &optional count ignored buffer) + (if (and buffer (eq buffer (current-buffer))) + (insert-char char count) + (save-excursion + (set-buffer buffer) + (insert-char char count)))) -(defun base64-encode-internal (str) - "Do base64 encoding on string STR and return the encoded string. -This code was converted to lisp code by me from the C code in -ftp://cs.utk.edu/pub/MIME/b64encode.c. Returns the entire string, -not broken up into `base64-max-line-length' byte lines." - (let ( - (word 0) ; The word to translate - w1 w2 w3 - ) - (cond - ((> (length str) 3) - (concat - (base64-encode-internal (substring str 0 3)) - (base64-encode-internal (substring str 3 nil)))) - ((= (length str) 3) - (setq w1 (aref str 0) - w2 (aref str 1) - w3 (aref str 2) - word (logior - (lsh (logand w1 255) 16) - (lsh (logand w2 255) 8) - (logand w3 255))) - (format "%c%c%c%c" (b0 word) (b1 word) (b2 word) (b3 word))) - ((= (length str) 2) - (setq w1 (aref str 0) - w2 (aref str 1) - word (logior - (lsh (logand w1 255) 16) - (lsh (logand w2 255) 8) - 0)) - (format "%c%c%c=" (b0 word) (b1 word) (b2 word))) - ((= (length str) 1) - (setq w1 (aref str 0) - word (logior - (lsh (logand w1 255) 16) - 0)) - (format "%c%c==" (b0 word) (b1 word))) - (t "")))) +(defun base64-decode-region (start end) + (interactive "r") + (message "Decoding base64...") + (let ((work-buffer nil) + (done nil) + (counter 0) + (bits 0) + (lim 0) inputpos + (non-data-chars (concat "^=" base64-alphabet))) + (unwind-protect + (save-excursion + (setq work-buffer (generate-new-buffer " *base64-work*")) + (buffer-disable-undo work-buffer) + (if base64-decoder-program + (let* ((binary-process-output t) ; any text already has CRLFs + (status (apply 'command-on-region + start end work-buffer + base64-decoder-program + base64-decoder-switches))) + (if (not (eq status t)) + (error "%s" (cdr status)))) + (goto-char start) + (skip-chars-forward non-data-chars end) + (while (not done) + (setq inputpos (point)) + (cond + ((> (skip-chars-forward base64-alphabet end) 0) + (setq lim (point)) + (while (< inputpos lim) + (setq bits (+ bits + (aref base64-alphabet-decoding-vector + (char-int (char-after inputpos))))) + (setq counter (1+ counter) + inputpos (1+ inputpos)) + (cond ((= counter 4) + (base64-insert-char (lsh bits -16) 1 nil work-buffer) + (base64-insert-char (logand (lsh bits -8) 255) 1 nil + work-buffer) + (base64-insert-char (logand bits 255) 1 nil + work-buffer) + (setq bits 0 counter 0)) + (t (setq bits (lsh bits 6))))))) + (cond + ((= (point) end) + (if (not (zerop counter)) + (error "at least %d bits missing at end of base64 encoding" + (* (- 4 counter) 6))) + (setq done t)) + ((= (char-after (point)) ?=) + (setq done t) + (cond ((= counter 1) + (error "at least 2 bits missing at end of base64 encoding")) + ((= counter 2) + (base64-insert-char (lsh bits -10) 1 nil work-buffer)) + ((= counter 3) + (base64-insert-char (lsh bits -16) 1 nil work-buffer) + (base64-insert-char (logand (lsh bits -8) 255) + 1 nil work-buffer)) + ((= counter 0) t))) + (t (skip-chars-forward non-data-chars end))))) + (or (markerp end) (setq end (set-marker (make-marker) end))) + (goto-char start) + (insert-buffer-substring work-buffer) + (delete-region (point) end)) + (and work-buffer (kill-buffer work-buffer)))) + (message "Decoding base64... done")) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Base64 decoding functions -;;; Most of the decoding code is courtesy Francesco Potorti` -;;; <F.Potorti@cnuce.cnr.it> -;;; this is much faster than my original code - thanks! -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(defun base64-decode-region (beg end) +(defun base64-encode-region (start end) (interactive "r") - (barf-if-buffer-read-only) - (let - ((exchange (= (point) beg)) - (endchars 0) - (list) (code)) - (goto-char beg) - (while (< (point) end) - (setq list (mapcar - (function - (lambda (c) - (cond - ((aref base64-decode-vector c)) - ((char-equal c ?=) - (setq endchars (1+ endchars)) - 0) - (nil - (error - "Character %c does not match Mime base64 coding" c))))) - (buffer-substring (point) (+ (point) 4)))) - (setq code (+ (nth 3 list) (lsh (nth 2 list) 6) - (lsh (nth 1 list) 12) (lsh (car list) 18))) - (delete-char 4) - (cond - ((zerop endchars) - (insert (% (lsh code -16) 256) (% (lsh code -8) 256) (% code 256))) - ((= endchars 1) - (insert (% (lsh code -16) 256) (% (lsh code -8) 256)) - (setq end (point))) - ((= endchars 2) - (insert (% (lsh code -16) 256)) - (setq end (point)))) - (if (char-equal (following-char) ?\n) - (progn (delete-char 1) - (setq end (- end 2))) - (setq end (1- end)))) - )) -; (if exchange -; (exchange-point-and-mark)))) + (message "Encoding base64...") + (let ((work-buffer nil) + (counter 0) + (cols 0) + (bits 0) + (alphabet base64-alphabet) + inputpos) + (unwind-protect + (save-excursion + (setq work-buffer (generate-new-buffer " *base64-work*")) + (buffer-disable-undo work-buffer) + (if base64-encoder-program + (let ((status (apply 'base64-run-command-on-region + start end work-buffer + base64-encoder-program + base64-encoder-switches))) + (if (not (eq status t)) + (error "%s" (cdr status)))) + (setq inputpos start) + (while (< inputpos end) + (setq bits (+ bits (char-int (char-after inputpos)))) + (setq counter (1+ counter)) + (cond ((= counter 3) + (base64-insert-char (aref alphabet (lsh bits -18)) 1 nil + work-buffer) + (base64-insert-char + (aref alphabet (logand (lsh bits -12) 63)) + 1 nil work-buffer) + (base64-insert-char + (aref alphabet (logand (lsh bits -6) 63)) + 1 nil work-buffer) + (base64-insert-char + (aref alphabet (logand bits 63)) + 1 nil work-buffer) + (setq cols (+ cols 4)) + (cond ((= cols 72) + (base64-insert-char ?\n 1 nil work-buffer) + (setq cols 0))) + (setq bits 0 counter 0)) + (t (setq bits (lsh bits 8)))) + (setq inputpos (1+ inputpos))) + ;; write out any remaining bits with appropriate padding + (if (= counter 0) + nil + (setq bits (lsh bits (- 16 (* 8 counter)))) + (base64-insert-char (aref alphabet (lsh bits -18)) 1 nil + work-buffer) + (base64-insert-char (aref alphabet (logand (lsh bits -12) 63)) + 1 nil work-buffer) + (if (= counter 1) + (base64-insert-char ?= 2 nil work-buffer) + (base64-insert-char (aref alphabet (logand (lsh bits -6) 63)) + 1 nil work-buffer) + (base64-insert-char ?= 1 nil work-buffer))) + (if (> cols 0) + (base64-insert-char ?\n 1 nil work-buffer))) + (or (markerp end) (setq end (set-marker (make-marker) end))) + (goto-char start) + (insert-buffer-substring work-buffer) + (delete-region (point) end)) + (and work-buffer (kill-buffer work-buffer)))) + (message "Encoding base64... done")) -(defun base64-decode (st &optional nd) - "Do base64 decoding on string STR and return the original string. -If given buffer positions, destructively decodes that area of the -current buffer." - (let ((replace-p nil) - (retval nil)) - (if (stringp st) - nil - (setq st (prog1 - (buffer-substring st (or nd (point-max))) - (delete-region st (or nd (point-max)))) - replace-p t)) - (setq retval - (save-excursion - (set-buffer (get-buffer-create " *b64decode*")) - (erase-buffer) - (insert st) - (goto-char (point-min)) - (while (re-search-forward "\r*\n" nil t) - (replace-match "")) - (goto-char (point-min)) - (base64-decode-region (point-min) (point-max)) - (buffer-string))) - (if replace-p (insert retval)) - retval)) +(defun base64-encode (string) + (save-excursion + (set-buffer (get-buffer-create " *base64-encode*")) + (erase-buffer) + (insert string) + (base64-encode-region (point-min) (point-max)) + (skip-chars-backward " \t\r\n") + (delete-region (point-max) (point)) + (prog1 + (buffer-string) + (kill-buffer (current-buffer))))) + +(defun base64-decode (string) + (save-excursion + (set-buffer (get-buffer-create " *base64-decode*")) + (erase-buffer) + (insert string) + (base64-decode-region (point-min) (point-max)) + (goto-char (point-max)) + (skip-chars-backward " \t\r\n") + (delete-region (point-max) (point)) + (prog1 + (buffer-string) + (kill-buffer (current-buffer))))) (provide 'base64)