;;; tm-edit.el --- Simple MIME Composer for GNU Emacs
-;; Copyright (C) 1993 .. 1996 Free Software Foundation, Inc.
+;; Copyright (C) 1993,1994,1995,1996,1997 Free Software Foundation, Inc.
;; Author: UMEDA Masanobu <umerin@mse.kyutech.ac.jp>
;; MORIOKA Tomohiko <morioka@jaist.ac.jp>
;; Maintainer: MORIOKA Tomohiko <morioka@jaist.ac.jp>
;; Created: 1994/08/21 renamed from mime.el
-;; Version: $Revision: 7.94 $
;; Keywords: mail, news, MIME, multimedia, multilingual
;; This file is part of tm (Tools for MIME).
;;; Commentary:
;; This is an Emacs minor mode for editing Internet multimedia
-;; messages formatted in MIME (RFC 1521 and RFC 1522). All messages in
-;; this mode are composed in the tagged MIME format, that are
-;; described in the following examples. The messages composed in the
-;; tagged MIME format are automatically translated into a MIME
-;; compliant message when exiting the mode.
+;; messages formatted in MIME (RFC 2045, 2046, 2047, 2048 and 2049).
+;; All messages in this mode are composed in the tagged MIME format,
+;; that are described in the following examples. The messages
+;; composed in the tagged MIME format are automatically translated
+;; into a MIME compliant message when exiting the mode.
;; Mule (a multilingual extension to Emacs 18 and 19) has a capability
;; of handling multilingual text in limited ISO-2022 manner that is
;; based on early experiences in Japanese Internet community and
-;; resulted in RFC 1468 (ISO-2022-JP charset for MIME). In order to
+;; resulted in RFC 1468 (ISO-2022-JP charset for MIME). In order to
;; enable multilingual capability in single text message in MIME,
;; charset of multilingual text written in Mule is declared as either
-;; `ISO-2022-JP-2' [RFC 1554] or `ISO-2022-INT-1'. Mule is required
-;; for reading the such messages.
+;; `ISO-2022-JP-2' [RFC 1554]. Mule is required for reading the such
+;; messages.
;; This MIME composer can work with Mail mode, mh-e letter Mode, and
;; News mode. First of all, you need the following autoload
;;
;;--[[text/plain]]
;; This is also a plain text. But, it is explicitly specified as is.
+;;--[[text/plain; charset=ISO-8859-1]]
+;; This is also a plain text. But charset is specified as iso-8859-1.
;;
-;;--[[text/plain; charset=ISO-2022-JP]]
-;; \e$B$3$l$O\e(B charset \e$B$r\e(B ISO-2022-JP \e$B$K;XDj$7$?F|K\8l$N\e(B plain \e$B%F%-%9%H$G$9\e(B.
-;;
-;;--[[text/richtext]]
+;; ¡Hola! Buenos días. ¿Cómo está usted?
+;;--[[text/enriched]]
;; <center>This is a richtext.</center>
;;
;;--[[image/gif][base64]]^M...image encoded in base64 comes here...
(require 'sendmail)
(require 'mail-utils)
(require 'mel)
-(require 'tl-822)
(require 'tl-list)
(require 'tm-view)
-(require 'tm-ew-e)
+(require 'eword-encode)
(require 'signature)
;;; @ version
;;;
-(defconst mime-editor/RCS-ID
- "$Id: tm-edit.el,v 7.94 1996/11/16 07:51:41 morioka Exp $")
-
-(defconst mime-editor/version (get-version-string mime-editor/RCS-ID))
+(defconst mime-editor/version "8.8 (Time Passed Me By)")
(defconst mime-editor/version-name
(concat "tm-edit " mime-editor/version))
("image"
("gif")
("jpeg")
+ ("png")
("tiff")
("x-pic")
("x-mag")
"text" "richtext" nil
nil
nil nil)
- ("\\.html$"
+ ("\\.\\(html\\|htm\\)$"
"text" "html" nil
nil
nil nil)
"quoted-printable"
"attachment" (("filename" . file))
)
- ("\\.jpg$"
+ ("\\.\\(jpeg\\|jpg\\)$"
"image" "jpeg" nil
"base64"
"inline" (("filename" . file))
"base64"
"inline" (("filename" . file))
)
- ("\\.tiff$"
+ ("\\.png$"
+ "image" "png" nil
+ "base64"
+ "inline" (("filename" . file))
+ )
+ ("\\.\\(tiff\\|tif\\)$"
"image" "tiff" nil
"base64"
"inline" (("filename" . file))
"base64"
"attachment" (("filename" . file))
)
+ ("\\.txt$"
+ "text" "plain" nil
+ nil
+ "attachment" (("filename" . file))
+ )
("\\.el$"
"application" "octet-stream" (("type" . "emacs-lisp"))
- "7bit"
+ nil
"attachment" (("filename" . file))
)
("\\.lsp$"
)
("\\.tar\\.gz$"
"application" "octet-stream" (("type" . "tar+gzip"))
- nil
+ "base64"
"attachment" (("filename" . file))
)
("\\.tgz$"
"application" "octet-stream" (("type" . "tar+gzip"))
- nil
+ "base64"
"attachment" (("filename" . file))
)
("\\.tar\\.Z$"
"application" "octet-stream" (("type" . "tar+compress"))
- nil
+ "base64"
"attachment" (("filename" . file))
)
("\\.taz$"
"application" "octet-stream" (("type" . "tar+compress"))
- nil
+ "base64"
"attachment" (("filename" . file))
)
("\\.gz$"
"application" "octet-stream" (("type" . "gzip"))
- nil
+ "base64"
"attachment" (("filename" . file))
)
("\\.Z$"
"application" "octet-stream" (("type" . "compress"))
- nil
+ "base64"
"attachment" (("filename" . file))
)
("\\.lzh$"
"application" "octet-stream" (("type" . "lha"))
- nil
+ "base64"
"attachment" (("filename" . file))
)
("\\.zip$"
"application" "zip" nil
- nil
+ "base64"
"attachment" (("filename" . file))
)
- ("\\.diff$"
+ ("\\.diffs?$"
"application" "octet-stream" (("type" . "patch"))
nil
"attachment" (("filename" . file))
;;;
(defvar mime-editor/transfer-level 7
- "*A number of network transfer level. It should be bigger than 7.")
+ "*A number of network transfer level. It should be bigger than 7.")
(make-variable-buffer-local 'mime-editor/transfer-level)
(defvar mime-editor/transfer-level-string
(defvar mime-editor/encrypting-type 'pgp-elkins
"*PGP encrypting type (pgp-elkins, pgp-kazu or nil). [tm-edit.el]")
-(defvar mime-editor/pgp-sign-function 'tm:mc-pgp-sign-region)
-(defvar mime-editor/pgp-encrypt-function 'tm:mc-pgp-encrypt-region)
-(defvar mime-editor/traditional-pgp-sign-function 'mc-pgp-sign-region)
-(defvar mime-editor/pgp-insert-public-key-function 'mc-insert-public-key)
-
-(autoload mime-editor/pgp-sign-function "tm-edit-mc")
-(autoload mime-editor/pgp-encrypt-function "tm-edit-mc")
-(autoload mime-editor/traditional-pgp-sign-function "mc-pgp")
-(autoload mime-editor/pgp-insert-public-key-function "mc-toplev")
-
;;; @@ about tag
;;;
(defconst mime-editor/menu-list
'((mime-help "Describe MIME editor mode" mime-editor/help)
(file "Insert File" mime-editor/insert-file)
+ (file "Insert File (verbose)" mime-editor/insert-file-verbose)
(external "Insert External" mime-editor/insert-external)
(voice "Insert Voice" mime-editor/insert-voice)
(message "Insert Message" mime-editor/insert-message)
(defun mime-editor/define-menu-for-xemacs ()
"Define menu for Emacs 19."
(cond ((featurep 'menubar)
- (make-local-variable 'current-menubar)
- (set-buffer-menubar current-menubar)
- (add-submenu nil
- (cons mime-editor/menu-title
- (mapcar (function
- (lambda (item)
- (vector (nth 1 item)(nth 2 item)
- mime/editor-mode-flag)
- ))
- mime-editor/menu-list)))
+ ;; (make-local-variable 'current-menubar)
+ ;; (set-buffer-menubar current-menubar)
+ ;; (add-submenu nil
+ ;; (cons mime-editor/menu-title
+ ;; (mapcar (function
+ ;; (lambda (item)
+ ;; (vector (nth 1 item)(nth 2 item)
+ ;; mime/editor-mode-flag)
+ ;; ))
+ ;; mime-editor/menu-list)))
+ (easy-menu-add
+ (cons mime-editor/menu-title
+ (mapcar (function
+ (lambda (item)
+ (vector (nth 1 item)(nth 2 item)
+ mime/editor-mode-flag)
+ ))
+ mime-editor/menu-list)))
)))
;;; modified by Steven L. Baur <steve@miranova.com>
In this mode, basically, the message is composed in the tagged MIME
format. The message tag looks like:
- `--[[text/plain; charset=ISO-2022-JP][7bit]]'.
+ --[[text/plain; charset=ISO-2022-JP][7bit]]
The tag specifies the MIME content type, subtype, optional parameters
and transfer encoding of the message following the tag. Messages
which key is MIME charset and value is coding-system.
Following commands are available in addition to major mode commands:
+
+\[make single part\]
\\[mime-editor/insert-text] insert a text message.
\\[mime-editor/insert-file] insert a (binary) file.
+\\[mime-editor/insert-file-verbose] insert a (binary) file, with verbose
+ MIME prompting.
\\[mime-editor/insert-external] insert a reference to external body.
\\[mime-editor/insert-voice] insert a voice message.
\\[mime-editor/insert-message] insert a mail or news message.
\\[mime-editor/insert-mail] insert a mail message.
\\[mime-editor/insert-signature] insert a signature file at end.
+\\[mime-editor/insert-key] insert PGP public key.
\\[mime-editor/insert-tag] insert a new MIME tag.
+
+\[make enclosure (maybe multipart)\]
\\[mime-editor/enclose-alternative-region] enclose as multipart/alternative.
\\[mime-editor/enclose-parallel-region] enclose as multipart/parallel.
\\[mime-editor/enclose-mixed-region] enclose as multipart/mixed.
\\[mime-editor/enclose-digest-region] enclose as multipart/digest.
\\[mime-editor/enclose-signed-region] enclose as PGP signed.
\\[mime-editor/enclose-encrypted-region] enclose as PGP encrypted.
-\\[mime-editor/insert-key] insert PGP public key.
+\\[mime-editor/enclose-quote-region] enclose as verbose mode (to avoid to expand tags)
+
+\[other commands\]
+\\[mime-editor/set-transfer-level-7bit] set transfer-level as 7.
+\\[mime-editor/set-transfer-level-8bit] set transfer-level as 8.
+\\[mime-editor/set-split] set message splitting mode.
+\\[mime-editor/set-sign] set PGP-sign mode.
+\\[mime-editor/set-encrypt] set PGP-encryption mode.
\\[mime-editor/preview-message] preview editing MIME message.
\\[mime-editor/exit] exit and translate into a MIME compliant message.
-\\[mime-editor/maybe-translate] exit and translate if in MIME mode, then split.
\\[mime-editor/help] show this help.
+\\[mime-editor/maybe-translate] exit and translate if in MIME mode, then split.
Additional commands are available in some major modes:
C-c C-c exit, translate and run the original command.
--[[text/plain]]
This is also a plain text. But, it is explicitly specified as
is.
- --[[text/plain; charset=ISO-2022-JP]]
- \e$B$3$l$O\e(B charset \e$B$r\e(B ISO-2022-JP \e$B$K;XDj$7$?F|K\8l$N\e(B plain \e$B%F%-%9\e(B
- \e$B%H$G$9\e(B.
- --[[text/richtext]]
- <center>This is a richtext.</center>
- --[[image/gif][base64]]^M...image encoded in base64 here...
- --[[audio/basic][base64]]^M...audio encoded in base64 here...
+ --[[text/plain; charset=ISO-8859-1]]
+ This is also a plain text. But charset is specified as
+ iso-8859-1.
+
+ ¡Hola! Buenos días. ¿Cómo está usted?
+ --[[text/enriched]]
+ This is a <bold>enriched text</bold>.
+ --[[image/gif][base64]]...image encoded in base64 here...
+ --[[audio/basic][base64]]...audio encoded in base64 here...
User customizable variables (not documented all of them):
mime-prefix
mime-ignore-trailing-spaces
Trailing white spaces in a message body are ignored if non-nil.
- mime-auto-fill-header
- Fill header fields that contain encoded-words if non-nil.
-
mime-auto-hide-body
Hide a non-textual body message encoded in base64 after insertion
if non-nil.
+ mime-editor/transfer-level
+ A number of network transfer level. It should be bigger than 7.
+ If you are in 8bit-through environment, please set 8.
+
mime-editor/voice-recorder
Specifies a function to record a voice message and encode it.
The function `mime-editor/voice-recorder-for-sun' is for Sun
;; Restore previous state.
(setq mime/editor-mode-flag nil)
(cond (running-xemacs
- (delete-menu-item (list mime-editor/menu-title)))
+ (if (featurep 'menubar)
+ (delete-menu-item (list mime-editor/menu-title))))
(t
(use-local-map mime/editor-mode-old-local-map)))
(defun mime-editor/insert-text ()
"Insert a text message.
-Charset is automatically obtained from the `mime/lc-charset-alist'."
+Charset is automatically obtained from the `charsets-mime-charset-alist'."
(interactive)
(let ((ret (mime-editor/insert-tag "text" nil nil)))
(if ret
(enriched-mode nil)
))))))
-(defun mime-editor/insert-file (file)
+(defun mime-editor/insert-file (file &optional verbose)
"Insert a message from a file."
- (interactive "fInsert file as MIME message: ")
+ (interactive "fInsert file as MIME message: \nP")
(let* ((guess (mime-find-file-type file))
- (pritype (nth 0 guess))
+ (type (nth 0 guess))
(subtype (nth 1 guess))
(parameters (nth 2 guess))
- (default (nth 3 guess)) ;Guess encoding from its file name.
+ (encoding (nth 3 guess))
(disposition-type (nth 4 guess))
(disposition-params (nth 5 guess))
- (encoding
- (if (not (interactive-p))
- default
- (completing-read
- (concat "What transfer encoding"
- (if default
- (concat " (default "
- (if (string-equal default "")
- "\"\""
- default)
- ")"
- ))
- ": ")
- mime-file-encoding-method-alist nil t nil))))
- (if (string-equal encoding "")
- (setq encoding default))
+ )
+ (if verbose
+ (setq type (mime-prompt-for-type type)
+ subtype (mime-prompt-for-subtype type subtype)
+ ))
+ (if (or (interactive-p) verbose (null encoding))
+ (setq encoding (mime-prompt-for-encoding encoding))
+ )
(if (or (consp parameters) (stringp disposition-type))
(let ((rest parameters) cell attribute value)
(setq parameters "")
)
))
))
- (mime-editor/insert-tag pritype subtype parameters)
+ (mime-editor/insert-tag type subtype parameters)
(mime-editor/insert-binary-file file encoding)
))
+;;
+;; mime-editor/insert-file-verbose exists so that users can access verbose
+;; functionality from menu picks, and not just key sequences.
+;;
+(defun mime-editor/insert-file-verbose (file)
+ "Insert a message from a file, with verbose MIME prompting"
+ (interactive "fInsert file as MIME message: \n")
+ (mime-editor/insert-file file t)
+ )
+
(defun mime-editor/insert-external ()
"Insert a reference to external body."
(interactive)
(let ((encoding
(completing-read
"What transfer encoding: "
- mime-file-encoding-method-alist nil t nil)))
+ (mime-encoding-alist) nil t nil)))
(mime-editor/insert-tag "audio" "basic" nil)
(mime-editor/define-encoding encoding)
(save-restriction
(defun mime-find-file-type (file)
"Guess Content-Type, subtype, and parameters from FILE."
(let ((guess nil)
- (guesses mime-file-types))
+ (guesses mime-file-types)
+ (case-fold-search t))
(while (and (not guess) guesses)
(if (string-match (car (car guesses)) file)
(setq guess (cdr (car guesses))))
guess
))
-(defun mime-prompt-for-type ()
+(defun mime-prompt-for-type (&optional default)
"Ask for Content-type."
(let ((type ""))
;; Repeat until primary content type is specified.
mime-content-types
nil
'require-match ;Type must be specified.
- nil
+ default
))
(if (string-equal type "")
(progn
(sit-for 1)
))
)
- type
- ))
-
-(defun mime-prompt-for-subtype (pritype)
- "Ask for Content-type subtype of Content-Type PRITYPE."
- (let* ((default (car (car (cdr (assoc pritype mime-content-types)))))
- (answer
+ type))
+
+(defun mime-prompt-for-subtype (type &optional default)
+ "Ask for subtype of media-type TYPE."
+ (let ((subtypes (cdr (assoc type mime-content-types))))
+ (or (and default
+ (assoc default subtypes))
+ (setq default (car (car subtypes)))
+ ))
+ (let* ((answer
(completing-read
(if default
(concat
"What content subtype: (default " default ") ")
"What content subtype: ")
- (cdr (assoc pritype mime-content-types))
+ (cdr (assoc type mime-content-types))
nil
'require-match ;Subtype must be specified.
nil
(mime-prompt-for-parameters-1 (cdr (assoc answer (cdr parameter)))))
))
-(defun mime-flag-region (from to flag)
- "Hides or shows lines from FROM to TO, according to FLAG.
-If FLAG is `\\n' (newline character) then text is shown,
-while if FLAG is `\\^M' (control-M) the text is hidden."
- (let ((buffer-read-only nil) ;Okay even if write protected.
- (modp (buffer-modified-p)))
- (unwind-protect
- (subst-char-in-region from to
- (if (= flag ?\n) ?\^M ?\n)
- flag t)
- (set-buffer-modified-p modp))))
+(defun mime-prompt-for-encoding (default)
+ "Ask for Content-Transfer-Encoding. [tm-edit.el]"
+ (let (encoding)
+ (while (string=
+ (setq encoding
+ (completing-read
+ "What transfer encoding: "
+ (mime-encoding-alist) nil t default)
+ )
+ ""))
+ encoding))
\f
;;; @ Translate the tagged MIME messages into a MIME compliant message.
(defun mime-editor/translate-header ()
"Encode the message header into network representation."
- (mime/encode-message-header 'code-conversion)
+ (eword-encode-header 'code-conversion)
(run-hooks 'mime-editor/translate-header-hook)
)
(insert (format "Content-Transfer-Encoding: %s\n" encoding))
)
(insert "\n")
- (or (funcall mime-editor/pgp-sign-function
- (point-min)(point-max) nil nil pgp-boundary)
+ (or (as-binary-process
+ (funcall (pgp-function 'mime-sign)
+ (point-min)(point-max) nil nil pgp-boundary))
(throw 'mime-editor/error 'pgp-error)
)
))))
(insert (format "Content-Transfer-Encoding: %s\n" encoding))
)
(insert "\n")
- (or (funcall mime-editor/pgp-encrypt-function
+ (or (funcall (pgp-function 'encrypt)
recipients (point-min) (point-max) from)
(throw 'mime-editor/error 'pgp-error)
)
)
(insert "\n")
(or (as-binary-process
- (funcall mime-editor/traditional-pgp-sign-function
+ (funcall (pgp-function 'traditional-sign)
beg (point-max)))
(throw 'mime-editor/error 'pgp-error)
)
)
(insert "\n")
(or (as-binary-process
- (funcall mime-editor/pgp-encrypt-function
+ (funcall (pgp-function 'encrypt)
recipients beg (point-max) nil 'maybe)
)
(throw 'mime-editor/error 'pgp-error)
(tag (buffer-substring beg end))
)
(delete-region beg end)
- (setq contype (mime-editor/get-contype tag))
- (setq encoding (mime-editor/get-encoding tag))
- (insert (concat prefix "--" boundary "\n"))
- (save-restriction
- (narrow-to-region (point)(point))
- (insert "Content-Type: " contype "\n")
- (if encoding
- (insert "Content-Transfer-Encoding: " encoding "\n"))
- (mime/encode-message-header)
- )
+ (let ((contype (mime-editor/get-contype tag))
+ (encoding (mime-editor/get-encoding tag))
+ )
+ (insert (concat prefix "--" boundary "\n"))
+ (save-restriction
+ (narrow-to-region (point)(point))
+ (insert "Content-Type: " contype "\n")
+ (if encoding
+ (insert "Content-Transfer-Encoding: " encoding "\n"))
+ (eword-encode-header)
+ ))
t)))
(defun mime-editor/translate-region (beg end &optional boundary multipart)
)
(encode-mime-charset-region beg (mime-editor/content-end)
charset)
- (mime-encode-region beg (mime-editor/content-end) encoding)
+ (if encoding
+ (mime-encode-region beg (mime-editor/content-end) encoding))
(mime-editor/define-encoding encoding)
))
(goto-char (mime-editor/content-end))
(interactive "P")
(mime-editor/insert-tag "application" "pgp-keys")
(mime-editor/define-encoding "7bit")
- (funcall mime-editor/pgp-insert-public-key-function)
+ (funcall (pgp-function 'insert-key))
)
(setq type ctype)
)
(cond
- ((string-equal type "multipart")
+ ((string= ctype "application/pgp-signature")
+ (delete-region (point-min)(point-max))
+ )
+ ((string= type "multipart")
(let* ((boundary (assoc-value "boundary" params))
(boundary-pat
(concat "\n--" (regexp-quote boundary) "[ \t]*\n"))
(t
(let* (charset
(pstr
- (mapconcat (function
- (lambda (attr)
- (if (string-equal (car attr)
- "charset")
- (progn
- (setq charset (cdr attr))
- "")
- (concat ";" (car attr)
- "=" (cdr attr))
- )
- ))
- params ""))
+ (let ((bytes (+ 14 (length ctype))))
+ (mapconcat (function
+ (lambda (attr)
+ (if (string-equal (car attr) "charset")
+ (progn
+ (setq charset (cdr attr))
+ "")
+ (let* ((str
+ (concat (car attr)
+ "=" (cdr attr))
+ )
+ (bs (length str))
+ )
+ (setq bytes (+ bytes bs 2))
+ (if (< bytes 76)
+ (concat "; " str)
+ (setq bytes (+ bs 1))
+ (concat ";\n " str)
+ )
+ ))))
+ params "")))
encoding
encoded)
(save-excursion