X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=mel-q.el;h=5c9f7c547e5c1af8ca51bb3cca6208246aa612ad;hb=e3697d7a1aa5dd7b573c5ff3f320ed03fd6614bd;hp=72a22761631f3b873ab1805748aac81097ec4499;hpb=89a2910b4ad0458a9670fffb54ac4a760c2abf56;p=elisp%2Fflim.git diff --git a/mel-q.el b/mel-q.el index 72a2276..5c9f7c5 100644 --- a/mel-q.el +++ b/mel-q.el @@ -1,13 +1,12 @@ -;;; mel-q.el: Quoted-Printable and Q-encoding encoder/decoder for GNU Emacs +;;; mel-q.el --- Quoted-Printable encoder/decoder. -;; Copyright (C) 1995,1996,1997 Free Software Foundation, Inc. +;; Copyright (C) 1995,96,97,98,99,2000,2001 Free Software Foundation, Inc. -;; Author: MORIOKA Tomohiko +;; Author: MORIOKA Tomohiko ;; Created: 1995/6/25 -;; Version: $Id: mel-q.el,v 7.1 1997/11/06 16:09:25 morioka Exp $ ;; Keywords: MIME, Quoted-Printable, Q-encoding -;; This file is part of MEL (MIME Encoding Library). +;; This file is part of FLIM (Faithful Library about Internet Message). ;; This program is free software; you can redistribute it and/or ;; modify it under the terms of the GNU General Public License as @@ -20,73 +19,79 @@ ;; General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the +;; along with this program; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;;; Code: -(require 'emu) +(require 'mime-def) +(require 'path-util) +(eval-when-compile + ;; XXX: should provide char-list instead of string-to-char-list. + ;; XXx: and also the macro `as-binary-process' should be provided + ;; XXx: by the module "pces" which will be loaded by way of "poem". + (require 'poem)) ;;; @ Quoted-Printable encoder ;;; -(defconst quoted-printable-hex-chars "0123456789ABCDEF") - (defsubst quoted-printable-quote-char (character) (concat "=" (char-to-string (aref quoted-printable-hex-chars (ash character -4))) - (char-to-string (aref quoted-printable-hex-chars (logand character 15))) - )) + (char-to-string (aref quoted-printable-hex-chars (logand character 15))))) (defun quoted-printable-internal-encode-region (start end) (save-excursion (save-restriction - (narrow-to-region start end) - (goto-char start) + (narrow-to-region (goto-char start) end) (let ((col 0) - enable-multibyte-characters) - (while (< (point)(point-max)) - (cond ((>= col 75) - (insert "=\n") - (setq col 0) - ) - ((looking-at "^From ") - (replace-match "=46rom ") - (backward-char 1) - (setq col (+ col 6)) - ) - ((looking-at "[ \t]\n") - (forward-char 1) - (insert "=\n") - (forward-char 1) - (setq col 0) - ) - (t - (let ((chr (char-after (point)))) - (cond ((= chr ?\n) - (forward-char 1) - (setq col 0) - ) - ((or (= chr ?\t) - (and (<= 32 chr)(/= chr ?=)(< chr 127)) - ) - (forward-char 1) - (setq col (1+ col)) - ) - ((>= col 73) - (insert "=\n") - (setq col 0) - ) - (t - (delete-char 1) - (insert (quoted-printable-quote-char chr)) - (setq col (+ col 3)) - )) - ))) - ))))) + chr) + (while (not (eobp)) + (cond + ((>= col 75) ; soft line break. + (insert "=\n") + (setq col 0)) + ((eolp) ; end of line. + (forward-char) + (setq col 0)) + (t + (setq chr (char-after (point))) + (cond + ((and (memq chr '(? ?\t)) ; encode WSP char before CRLF. + (eq (char-after (1+ (point))) ?\n)) + (forward-char) + (insert "=\n") + (forward-char) + (setq col 0)) + ((and (bolp) ; "^From " is not safe. + (eq chr ?F) + (eq (char-after (1+ (point))) ?r) + (eq (char-after (+ 2 (point))) ?o) + (eq (char-after (+ 3 (point))) ?m) + (eq (char-after (+ 4 (point))) ? )) + (delete-region (point)(1+ (point))) + (insert "=46") ; moved to ?r. + (forward-char 4) ; skip "rom ". + (setq col 7)) + ((or (= chr ?\t) ; skip safe char. + (and (<= 32 chr)(/= chr ?=)(< chr 127))) + (forward-char) + (setq col (1+ col))) + ((>= col 73) ; soft line break. + (insert "=\n") + (setq col 0)) + (t ; encode unsafe char. + (delete-region (point)(1+ (point))) + ;; (insert (quoted-printable-quote-char chr)) + (insert + ?= + (aref quoted-printable-hex-chars (ash chr -4)) + (aref quoted-printable-hex-chars (logand chr 15))) + (setq col (+ col 3))))))))))) + (defvar quoted-printable-external-encoder '("mmencode" "-q") "*list of quoted-printable encoder program name and its arguments.") @@ -98,15 +103,14 @@ (as-binary-process (apply (function call-process-region) start end (car quoted-printable-external-encoder) - t t nil (cdr quoted-printable-external-encoder)) - ) + t t nil + (cdr quoted-printable-external-encoder))) ;; for OS/2 ;; regularize line break code (goto-char (point-min)) (while (re-search-forward "\r$" nil t) - (replace-match "") - ) - ))) + (replace-match ""))))) + (defvar quoted-printable-internal-encoding-limit (if (and (featurep 'xemacs)(featurep 'mule)) @@ -114,7 +118,8 @@ (require 'path-util) (if (exec-installed-p "mmencode") 1000 - (message "Don't found external encoder for Quoted-Printable!") + ;; XXX: Fix this message, or simply remove it. + ;; (message "Don't found external encoder for Quoted-Printable!") nil)) "*limit size to use internal quoted-printable encoder. If size of input to encode is larger than this limit, @@ -128,85 +133,77 @@ region is smaller than `quoted-printable-internal-encoding-limit', otherwise it calls external quoted-printable encoder specified by `quoted-printable-external-encoder'. In this case, you must install the program (maybe mmencode included in metamail or XEmacs package)." - (interactive "r") + (interactive "*r") (if (and quoted-printable-internal-encoding-limit (> (- end start) quoted-printable-internal-encoding-limit)) (quoted-printable-external-encode-region start end) - (quoted-printable-internal-encode-region start end) - )) + (quoted-printable-internal-encode-region start end))) (defun quoted-printable-encode-string (string) "Encode STRING to quoted-printable, and return the result." (with-temp-buffer (insert string) (quoted-printable-encode-region (point-min)(point-max)) - (buffer-string) - )) + (buffer-string))) + + +(mel-define-method-function + (mime-encode-string string (nil "quoted-printable")) + 'quoted-printable-encode-string) + +(mel-define-method-function + (mime-encode-region start end (nil "quoted-printable")) + 'quoted-printable-encode-region) -(defun quoted-printable-insert-encoded-file (filename) +(mel-define-method mime-insert-encoded-file (filename (nil "quoted-printable")) "Encode contents of file FILENAME to quoted-printable, and insert the result. It calls external quoted-printable encoder specified by `quoted-printable-external-encoder'. So you must install the program \(maybe mmencode included in metamail or XEmacs package)." - (interactive (list (read-file-name "Insert encoded file: "))) - (apply (function call-process) (car quoted-printable-external-encoder) - filename t nil (cdr quoted-printable-external-encoder)) - ) + (interactive "*fInsert encoded file: ") + (apply (function call-process) + (car quoted-printable-external-encoder) + filename t nil + (cdr quoted-printable-external-encoder))) ;;; @ Quoted-Printable decoder ;;; -(defun quoted-printable-decode-string (string) - "Decode STRING which is encoded in quoted-printable, and return the result." - (let (q h l) - (mapconcat (function - (lambda (chr) - (cond ((eq chr ?=) - (setq q t) - "") - (q (setq h - (cond ((<= ?a chr) (+ (- chr ?a) 10)) - ((<= ?A chr) (+ (- chr ?A) 10)) - ((<= ?0 chr) (- chr ?0)) - )) - (setq q nil) - "") - (h (setq l (cond ((<= ?a chr) (+ (- chr ?a) 10)) - ((<= ?A chr) (+ (- chr ?A) 10)) - ((<= ?0 chr) (- chr ?0)) - )) - (prog1 - (char-to-string (logior (ash h 4) l)) - (setq h nil) - ) - ) - (t (char-to-string chr)) - ))) - string ""))) - -(defconst quoted-printable-octet-regexp - (concat "=[" quoted-printable-hex-chars - "][" quoted-printable-hex-chars "]")) +(defsubst quoted-printable-hex-char-to-num (chr) + (cond ((<= ?a chr) (+ (- chr ?a) 10)) + ((<= ?A chr) (+ (- chr ?A) 10)) + ((<= ?0 chr) (- chr ?0)) + )) (defun quoted-printable-internal-decode-region (start end) (save-excursion (save-restriction (narrow-to-region start end) (goto-char (point-min)) - (while (re-search-forward "=\n" nil t) - (replace-match "") - ) - (goto-char (point-min)) - (let (b e str) - (while (re-search-forward quoted-printable-octet-regexp nil t) - (setq b (match-beginning 0)) - (setq e (match-end 0)) - (setq str (buffer-substring b e)) - (delete-region b e) - (insert (quoted-printable-decode-string str)) - )) - ))) + (while (search-forward "=" nil t) + (cond + ((eolp) + ;; unfold soft line break. + (delete-region (1- (point))(1+ (point)))) + ((and (memq (char-after (point)) + (eval-when-compile + ;; XXX: should provide char-list instead. + (string-to-char-list quoted-printable-hex-chars))) + (memq (char-after (1+ (point))) + (eval-when-compile + ;; XXX: should provide char-list instead. + (string-to-char-list quoted-printable-hex-chars)))) + ;; encoded char. + (insert + (prog1 + (logior + (ash (quoted-printable-hex-char-to-num (char-after (point))) 4) + (quoted-printable-hex-char-to-num (char-after (1+ (point))))) + (delete-region (1- (point))(+ 2 (point)))))) + (t + ;; invalid encoding. + )))))) (defvar quoted-printable-external-decoder '("mmencode" "-q" "-u") "*list of quoted-printable decoder program name and its arguments.") @@ -216,8 +213,9 @@ It calls external quoted-printable encoder specified by (as-binary-process (apply (function call-process-region) start end (car quoted-printable-external-decoder) - t t nil (cdr quoted-printable-external-decoder)) - ))) + t t nil + (cdr quoted-printable-external-decoder))))) + (defvar quoted-printable-internal-decoding-limit nil "*limit size to use internal quoted-printable decoder. @@ -232,12 +230,53 @@ region is smaller than `quoted-printable-internal-decoding-limit', otherwise it calls external quoted-printable decoder specified by `quoted-printable-external-decoder'. In this case, you must install the program (maybe mmencode included in metamail or XEmacs package)." - (interactive "r") + (interactive "*r") (if (and quoted-printable-internal-decoding-limit (> (- end start) quoted-printable-internal-decoding-limit)) (quoted-printable-external-decode-region start end) - (quoted-printable-internal-decode-region start end) - )) + (quoted-printable-internal-decode-region start end))) + +(defun quoted-printable-decode-string (string) + "Decode STRING which is encoded in quoted-printable, and return the result." + (with-temp-buffer + (insert string) + (quoted-printable-decode-region (point-min)(point-max)) + (buffer-string))) + + +(mel-define-method-function + (mime-decode-string string (nil "quoted-printable")) + 'quoted-printable-decode-string) + +(mel-define-method-function + (mime-decode-region start end (nil "quoted-printable")) + 'quoted-printable-decode-region) + + +(defvar quoted-printable-external-decoder-option-to-specify-file '("-o") + "*list of options of quoted-printable decoder program to specify file. +If the quoted-printable decoder does not have such option, set this as nil.") + +(mel-define-method mime-write-decoded-region (start end filename + (nil "quoted-printable")) + "Decode and write current region encoded by quoted-printable into FILENAME. +START and END are buffer positions." + (interactive "*r\nFWrite decoded region to file: ") + (as-binary-process + (apply (function call-process-region) + start end (car quoted-printable-external-decoder) + (null quoted-printable-external-decoder-option-to-specify-file) + (unless quoted-printable-external-decoder-option-to-specify-file + (list (current-buffer) nil)) + nil + (delq nil + (append + (cdr quoted-printable-external-decoder) + quoted-printable-external-decoder-option-to-specify-file + (when quoted-printable-external-decoder-option-to-specify-file + (list filename)))))) + (unless quoted-printable-external-decoder-option-to-specify-file + (write-region-as-binary (point-min) (point-max) filename))) ;;; @ Q-encoding encode/decode string @@ -255,22 +294,16 @@ the program (maybe mmencode included in metamail or XEmacs package)." MODE allows `text', `comment', `phrase' or nil. Default value is `phrase'." (let ((specials (cdr (or (assq mode q-encoding-special-chars-alist) - (assq 'phrase q-encoding-special-chars-alist) - )))) + (assq 'phrase q-encoding-special-chars-alist))))) (mapconcat (function (lambda (chr) (cond ((eq chr ? ) "_") ((or (< chr 32) (< 126 chr) - (memq chr specials) - ) - (quoted-printable-quote-char chr) - ) + (memq chr specials)) + (quoted-printable-quote-char chr)) (t - (char-to-string chr) - )) - )) - string "") - )) + (char-to-string chr))))) + string ""))) (defun q-encoding-decode-string (string) "Decode STRING which is encoded in Q-encoding and return the result." @@ -281,50 +314,25 @@ MODE allows `text', `comment', `phrase' or nil. Default value is ((eq chr ?=) (setq q t) "") - (q (setq h (cond ((<= ?a chr) (+ (- chr ?a) 10)) - ((<= ?A chr) (+ (- chr ?A) 10)) - ((<= ?0 chr) (- chr ?0)) - )) + (q (setq h (quoted-printable-hex-char-to-num chr)) (setq q nil) "") - (h (setq l (cond ((<= ?a chr) (+ (- chr ?a) 10)) - ((<= ?A chr) (+ (- chr ?A) 10)) - ((<= ?0 chr) (- chr ?0)) - )) + (h (setq l (quoted-printable-hex-char-to-num chr)) (prog1 (char-to-string (logior (ash h 4) l)) - (setq h nil) - ) - ) - (t (char-to-string chr)) - ))) + (setq h nil))) + (t (char-to-string chr))))) string ""))) +(mel-define-method-function (encoded-text-encode-string string (nil "Q")) + 'q-encoding-encode-string) -;;; @@ etc -;;; - -(defun q-encoding-printable-char-p (chr mode) - (and (not (memq chr '(?= ?? ?_))) - (<= ?\ chr)(<= chr ?~) - (cond ((eq mode 'text) t) - ((eq mode 'comment) - (not (memq chr '(?\( ?\) ?\\))) - ) - (t - (string-match "[A-Za-z0-9!*+/=_---]" (char-to-string chr)) - )))) - -(defun q-encoding-encoded-length (string &optional mode) - (let ((l 0)(i 0)(len (length string)) chr) - (while (< i len) - (setq chr (elt string i)) - (if (q-encoding-printable-char-p chr mode) - (setq l (+ l 1)) - (setq l (+ l 3)) - ) - (setq i (+ i 1)) ) - l)) +(mel-define-method encoded-text-decode-string (string (nil "Q")) + (if (string-match (eval-when-compile + (concat "\\`" Q-encoded-text-regexp "\\'")) + string) + (q-encoding-decode-string string) + (error "Invalid encoded-text %s" string))) ;;; @ end @@ -332,4 +340,4 @@ MODE allows `text', `comment', `phrase' or nil. Default value is (provide 'mel-q) -;;; mel-q.el ends here +;;; mel-q.el ends here.