;;; mime-edit.el --- Simple MIME Composer for GNU Emacs
-;; Copyright (C) 1993,1994,1995,1996,1997 Free Software Foundation, Inc.
+;; Copyright (C) 1993,94,95,96,97,98,99,2000,01,02,03
+;; 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>
+;; MORIOKA Tomohiko <tomo@kanji.zinbun.kyoto-u.ac.jp>
+;; Daiki Ueno <ueno@ueda.info.waseda.ac.jp>
;; Created: 1994/08/21 renamed from mime.el
;; Renamed: 1997/2/21 from tm-edit.el
-;; Version: $Revision: 0.73 $
;; Keywords: MIME, multimedia, multilingual, mail, news
-;; This file is part of SEMI (SEMI is Emacs MIME Interfaces).
+;; This file is part of SEMI (Sophisticated Emacs MIME Interfaces).
;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; 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
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;; Commentary:
;;
;; This is a conventional plain text. It should be translated into
;; text/plain.
-;;
+;;
;;--[[text/plain]]
;; This is also a plain text. But, it is explicitly specified as is.
;;--[[text/plain; charset=ISO-8859-1]]
;;; Code:
-(require 'emu)
(require 'sendmail)
(require 'mail-utils)
(require 'mel)
(require 'mime-view)
-(require 'eword-encode)
(require 'signature)
(require 'alist)
+(require 'invisible)
+(require 'pgg-def)
+(require 'pgg-parse)
+
+(autoload 'pgg-encrypt-region "pgg"
+ "PGP encryption of current region." t)
+(autoload 'pgg-sign-region "pgg"
+ "PGP signature of current region." t)
+(autoload 'pgg-insert-key "pgg"
+ "Insert PGP public key at point." t)
+(autoload 'smime-encrypt-region "smime"
+ "S/MIME encryption of current region.")
+(autoload 'smime-sign-region "smime"
+ "S/MIME signature of current region.")
+(defvar smime-output-buffer)
+(defvar smime-errors-buffer)
;;; @ version
;;;
-(defconst mime-edit-RCS-ID
- "$Id: mime-edit.el,v 0.73 1997-03-15 20:36:32 morioka Exp $")
-
-(defconst mime-edit-version (get-version-string mime-edit-RCS-ID))
-
-(defconst mime-edit-version-name
- (concat "SEMI MIME-Edit " mime-edit-version))
+(eval-and-compile
+ (defconst mime-edit-version
+ (concat
+ (mime-product-name mime-user-interface-product) " "
+ (mapconcat #'number-to-string
+ (mime-product-version mime-user-interface-product) ".")
+ " - \"" (mime-product-code-name mime-user-interface-product) "\"")))
;;; @ variables
;;;
-(defvar mime-ignore-preceding-spaces nil
- "*Ignore preceding white spaces if non-nil.")
+(defgroup mime-edit nil
+ "MIME edit mode"
+ :group 'mime)
+
+(defcustom mime-ignore-preceding-spaces nil
+ "*Ignore preceding white spaces if non-nil."
+ :group 'mime-edit
+ :type 'boolean)
-(defvar mime-ignore-trailing-spaces nil
- "*Ignore trailing white spaces if non-nil.")
+(defcustom mime-ignore-trailing-spaces nil
+ "*Ignore trailing white spaces if non-nil."
+ :group 'mime-edit
+ :type 'boolean)
-(defvar mime-ignore-same-text-tag t
+(defcustom mime-ignore-same-text-tag t
"*Ignore preceding text content-type tag that is same with new one.
-If non-nil, the text tag is not inserted unless something different.")
+If non-nil, the text tag is not inserted unless something different."
+ :group 'mime-edit
+ :type 'boolean)
-(defvar mime-auto-hide-body t
- "*Hide non-textual body encoded in base64 after insertion if non-nil.")
+(defcustom mime-auto-hide-body t
+ "*Hide non-textual body encoded in base64 after insertion if non-nil."
+ :group 'mime-edit
+ :type 'boolean)
-(defvar mime-edit-voice-recorder
+(defcustom mime-edit-voice-recorder
(function mime-edit-voice-recorder-for-sun)
- "*Function to record a voice message and encode it. [mime-edit.el]")
+ "*Function to record a voice message and encode it."
+ :group 'mime-edit
+ :type 'function)
-(defvar mime-edit-mode-hook nil
- "*Hook called when enter MIME mode.")
+(defcustom mime-edit-mode-hook nil
+ "*Hook called when enter MIME mode."
+ :group 'mime-edit
+ :type 'hook)
-(defvar mime-edit-translate-hook nil
+(defcustom mime-edit-translate-hook nil
"*Hook called before translating into a MIME compliant message.
To insert a signature file automatically, call the function
-`mime-edit-insert-signature' from this hook.")
+`mime-edit-insert-signature' from this hook."
+ :group 'mime-edit
+ :type 'hook)
-(defvar mime-edit-exit-hook nil
- "*Hook called when exit MIME mode.")
+(defcustom mime-edit-exit-hook nil
+ "*Hook called when exit MIME mode."
+ :group 'mime-edit
+ :type 'hook)
(defvar mime-content-types
'(("text"
("plain"
;;("charset" "" "ISO-2022-JP" "US-ASCII" "ISO-8859-1" "ISO-8859-8")
)
- ("richtext"
- ;;("charset" "" "ISO-2022-JP" "US-ASCII" "ISO-8859-1" "ISO-8859-8")
- )
- ("enriched"
- ;;("charset" "" "ISO-2022-JP" "US-ASCII" "ISO-8859-1" "ISO-8859-8")
- )
- ("x-latex"
- ;;("charset" "" "ISO-2022-JP" "US-ASCII" "ISO-8859-1" "ISO-8859-8")
- )
- ("html"
- ;;("charset" "" "ISO-2022-JP" "US-ASCII" "ISO-8859-1" "ISO-8859-8")
- )
- ("x-rot13-47")
+ ("enriched")
+ ("html")
+ ("css") ; rfc2318
+ ("csv") ; rfc4180
+ ("xml") ; rfc2376
+ ("x-latex")
+ ;; ("x-rot13-47-48")
)
("message"
("external-body"
("tftp" ("site") ("name"))
("afs" ("site") ("name"))
("local-file" ("site") ("name"))
- ("mail-server" ("server" "ftpmail@nic.karrn.ad.jp"))
+ ("mail-server"
+ ("server" "ftpmail@nic.karrn.ad.jp")
+ ("subject"))
+ ("url" ("url"))
))
("rfc822")
+ ("news")
)
("application"
+ ("javascript")
+ ("msword")
("octet-stream" ("type" "" "tar" "shar"))
("postscript")
+ ("pdf")
+ ("rtf")
+ ("zip")
+ ("x-shockwave-flash")
+ ("x-7z-compressed")
+
+ ; OpenOffice
+ ("vnd.oasis.opendocument.text")
+ ("vnd.oasis.opendocument.spreadsheet")
+ ("vnd.oasis.opendocument.graphics")
+ ("vnd.oasis.opendocument.chart")
+ ("vnd.oasis.opendocument.formula")
+ ("vnd.oasis.opendocument.text-master")
+ ("vnd.oasis.opendocument.presentation")
+ ("vnd.oasis.opendocument.text-template")
+ ("vnd.oasis.opendocument.spreadsheet-template")
+ ("vnd.oasis.opendocument.presentation-template")
+ ("vnd.oasis.opendocument.graphics-template")
+
+ ("msword")
+ ("vnd.ms-excel")
+ ("vnd.ms-powerpoint")
+ ; Microsoft Office (OpenXML)
+ ("vnd.ms-excel.addin.macroEnabled.12")
+ ("vnd.ms-excel.sheet.binary.macroEnabled.12")
+ ("vnd.ms-excel.sheet.macroEnabled.12")
+ ("vnd.ms-excel.template.macroEnabled.12")
+ ("vnd.ms-powerpoint.addin.macroEnabled.12")
+ ("vnd.ms-powerpoint.presentation.macroEnabled.12")
+ ("vnd.ms-powerpoint.slideshow.macroEnabled.12")
+ ("vnd.ms-powerpoint.template.macroEnabled.12")
+ ("vnd.ms-word.document.macroEnabled.12")
+ ("vnd.ms-word.template.macroEnabled.12")
+ ("vnd.openxmlformats-officedocument.presentationml.presentation")
+ ("vnd.openxmlformats-officedocument.presentationml.slideshow")
+ ("vnd.openxmlformats-officedocument.presentationml.template")
+ ("vnd.openxmlformats-officedocument.spreadsheetml.sheet")
+ ("vnd.openxmlformats-officedocument.spreadsheetml.template")
+ ("vnd.openxmlformats-officedocument.wordprocessingml.document")
+ ("vnd.openxmlformats-officedocument.wordprocessingml.template")
+ ("vnd.ms-xpsdocument")
+ ; Microsoft Project
+ ("vnd.ms-project")
("x-kiss" ("x-cnf")))
("image"
+ ("bmp")
("gif")
("jpeg")
+ ("png")
+ ("svg+xml")
("tiff")
("x-pic")
("x-mag")
("x-xwd")
- ("x-xbm")
- )
- ("audio" ("basic"))
- ("video" ("mpeg"))
- )
+ ("x-xbm"))
+ ("audio"
+ ("basic")
+ ("mpeg")
+ ("ogg")
+ ("vorbis"))
+ ("video"
+ ("mpeg")
+ ("ogg")
+ ("mp4")
+ ("quicktime")
+ ("x-flv")))
"*Alist of content-type, subtype, parameters and its values.")
-(defvar mime-file-types
- '(("\\.rtf$"
- "text" "richtext" nil
+(defcustom mime-file-types
+ '(
+
+ ;; Programming languages
+
+ ("\\.cc$"
+ "application" "octet-stream" (("type" . "C++"))
+ "7bit"
+ "attachment" (("filename" . file))
+ )
+
+ ("\\.el$"
+ "application" "octet-stream" (("type" . "emacs-lisp"))
+ "7bit"
+ "attachment" (("filename" . file))
+ )
+
+ ("\\.lsp$"
+ "application" "octet-stream" (("type" . "common-lisp"))
+ "7bit"
+ "attachment" (("filename" . file))
+ )
+
+ ("\\.pl$"
+ "application" "octet-stream" (("type" . "perl"))
+ "7bit"
+ "attachment" (("filename" . file))
+ )
+
+ ;; Text or translated text
+
+ ("\\.txt$\\|\\.pln$"
+ "text" "plain" nil
nil
- nil nil)
+ "inline" (("filename" . file))
+ )
+
+ ("\\.css$"
+ "text" "css" nil
+ nil
+ "inline" (("filename" . file))
+ )
+
+ ("\\.csv$"
+ "text" "csv" nil
+ nil
+ "inline" (("filename" . file))
+ )
+
+ ("\\.tex$\\|\\.latex$"
+ "text" "x-latex" nil
+ nil
+ "inline" (("filename" . file))
+ )
+
+ ;; .rc : procmail modules pm-xxxx.rc
+ ;; *rc : other resource files
+
+ ("\\.\\(rc\\|lst\\|log\\|sql\\|mak\\)$\\|\\..*rc$"
+ "text" "plain" nil
+ nil
+ "attachment" (("filename" . file))
+ )
+
("\\.html$"
"text" "html" nil
nil
nil nil)
+
+ ("\\.diff$\\|\\.patch$"
+ "application" "octet-stream" (("type" . "patch"))
+ nil
+ "attachment" (("filename" . file))
+ )
+
+ ("\\.signature"
+ "text" "plain" nil nil nil nil)
+
+
+ ("\\.js$"
+ "application" "javascript" nil
+ nil
+ "inline" (("filename" . file))
+ )
+
+
+ ;; Microsoft Project
+ ("\\.mpp$"
+ "application" "vnd.ms-project" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+
+
+ ;; Microsoft Office (none-OpenXML)
+
+ ("\\.rtf$" ; Rich text format
+ "application" "rtf" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.doc$" ;MS Word
+ "application" "msword" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.xls$" ; MS Excel
+ "application" "vnd.ms-excel" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.ppt$" ; MS Power Point
+ "application" "vnd.ms-powerpoint" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+
+
+ ;; Microsoft Office (OpenXML)
+
+ ; MS Word
+ ("\\.docm$"
+ "application" "vnd.ms-word.document.macroEnabled.12" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.docx$"
+ "application" "vnd.openxmlformats-officedocument.wordprocessingml.document" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.dotm$"
+ "application" "vnd.ms-word.template.macroEnabled.12" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.dotx$"
+ "application" "vnd.openxmlformats-officedocument.wordprocessingml.template" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+
+ ; MS Power Point
+ ("\\.potm$"
+ "application" "vnd.ms-powerpoint.template.macroEnabled.12" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.potx$"
+ "application" "vnd.openxmlformats-officedocument.presentationml.template" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.ppam$"
+ "application" "vnd.ms-powerpoint.addin.macroEnabled.12" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.ppsm$"
+ "application" "vnd.ms-powerpoint.slideshow.macroEnabled.12" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.ppsx$"
+ "application" "vnd.openxmlformats-officedocument.presentationml.slideshow" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.pptm$"
+ "application" "vnd.ms-powerpoint.presentation.macroEnabled.12" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.pptx$"
+ "application" "vnd.openxmlformats-officedocument.presentationml.presentation" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+
+ ; MS Excel
+ ("\\.xlam$"
+ "application" "vnd.ms-excel.addin.macroEnabled.12" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.xlsb$"
+ "application" "vnd.ms-excel.sheet.binary.macroEnabled.12" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.xlsm$"
+ "application" "vnd.ms-excel.sheet.macroEnabled.12" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.xlsx$"
+ "application" "vnd.openxmlformats-officedocument.spreadsheetml.sheet" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.xltm$"
+ "application" "vnd.ms-excel.template.macroEnabled.12" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.xltx$"
+ "application" "vnd.openxmlformats-officedocument.spreadsheetml.template" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+
+
+ ;; Open Office
+ ("\\.odt$"
+ "application" "vnd.oasis.opendocument.text" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.ods$"
+ "application" "vnd.oasis.opendocument.spreadsheet" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.odg$"
+ "application" "vnd.oasis.opendocument.graphics" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.odf$"
+ "application" "vnd.oasis.opendocument.formula" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.odm$"
+ "application" "vnd.oasis.opendocument.text-master" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.odp$"
+ "application" "vnd.oasis.opendocument.presentation" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.ott$"
+ "application" "vnd.oasis.opendocument.text-template" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.ots$"
+ "application" "vnd.oasis.opendocument.spreadsheet-template" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.otp$"
+ "application" "vnd.oasis.opendocument.presentation-template" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.otg$"
+ "application" "vnd.oasis.opendocument.graphics-template" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+
+ ;; Postscript and PDF
("\\.ps$"
"application" "postscript" nil
- "quoted-printable"
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.pdf$"
+ "application" "pdf" nil
+ "base64"
"attachment" (("filename" . file))
)
- ("\\.jpg$"
+
+ ;; Pure binary
+
+ ("\\.jpg$\\|\\.jpeg$"
"image" "jpeg" nil
"base64"
"inline" (("filename" . file))
"base64"
"inline" (("filename" . file))
)
+ ("\\.png$"
+ "image" "png" nil
+ "base64"
+ "inline" (("filename" . file))
+ )
+ ("\\.bmp$"
+ "image" "bmp" nil
+ "base64"
+ "inline" (("filename" . file))
+ )
+ ("\\.svg$"
+ "image" "svg+xml" nil
+ "base64"
+ "inline" (("filename" . file))
+ )
("\\.tiff$"
"image" "tiff" nil
"base64"
"base64"
"inline" (("filename" . file))
)
- ("\\.au$"
+
+ ;; Audio and video
+
+ ("\\.au$\\|\\.snd$"
"audio" "basic" nil
"base64"
"attachment" (("filename" . file))
)
- ("\\.mpg$"
+ ("\\.mp[234]\\|\\.m4[abp]$"
+ "audio" "mpeg" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.ogg$"
+ "audio" "ogg" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.ogg$"
+ "audio" "vorbis" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.mpg\\|\\.mpeg$"
"video" "mpeg" nil
"base64"
"attachment" (("filename" . file))
)
- ("\\.el$"
- "application" "octet-stream" (("type" . "emacs-lisp"))
- "7bit"
+ ("\\.mp4\\|\\.m4v$"
+ "video" "mp4" nil
+ "base64"
"attachment" (("filename" . file))
)
- ("\\.lsp$"
- "application" "octet-stream" (("type" . "common-lisp"))
- "7bit"
+ ("\\.qt$\\|\\.mov$"
+ "video" "quicktime" nil
+ "base64"
"attachment" (("filename" . file))
)
+ ("\\.flv$"
+ "video" "x-flv" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+ ("\\.swf$"
+ "application" "x-shockwave-flash" nil
+ "base64"
+ "attachment" (("filename" . file))
+ )
+
+
+ ;; Compressed files
+
("\\.tar\\.gz$"
"application" "octet-stream" (("type" . "tar+gzip"))
"base64"
"base64"
"attachment" (("filename" . file))
)
- ("\\.diff$"
- "application" "octet-stream" (("type" . "patch"))
- nil
- "attachment" (("filename" . file))
- )
- ("\\.patch$"
- "application" "octet-stream" (("type" . "patch"))
- nil
+ ("\\.7z$"
+ "application" "x-7z-compressed" nil
+ "base64"
"attachment" (("filename" . file))
)
- ("\\.signature"
- "text" "plain" nil nil)
+
+ ;; Rest
+
(".*"
"application" "octet-stream" nil
nil
- "attachment" (("filename" . file))
- )
+ "attachment" (("filename" . file)))
)
"*Alist of file name, types, parameters, and default encoding.
-If encoding is nil, it is determined from its contents.")
+If encoding is nil, it is determined from its contents."
+ :type `(repeat
+ (list regexp
+ ;; primary-type
+ (choice :tag "Primary-Type"
+ ,@(nconc (mapcar (lambda (cell)
+ (list 'item (car cell))
+ )
+ mime-content-types)
+ '(string)))
+ ;; subtype
+ (choice :tag "Sub-Type"
+ ,@(nconc
+ (apply #'nconc
+ (mapcar (lambda (cell)
+ (mapcar (lambda (cell)
+ (list 'item (car cell))
+ )
+ (cdr cell)))
+ mime-content-types))
+ '(string)))
+ ;; parameters
+ (repeat :tag "Parameters of Content-Type field"
+ (cons string (choice string symbol)))
+ ;; content-transfer-encoding
+ (choice :tag "Encoding"
+ ,@(cons
+ '(const nil)
+ (mapcar (lambda (cell)
+ (list 'item cell)
+ )
+ (mime-encoding-list))))
+ ;; disposition-type
+ (choice :tag "Disposition-Type"
+ (item nil)
+ (item "inline")
+ (item "attachment")
+ string)
+ ;; parameters
+ (repeat :tag "Parameters of Content-Disposition field"
+ (cons string (choice string symbol)))
+ ))
+ :group 'mime-edit)
;;; @@ about charset, encoding and transfer-level
(iso-8859-7 8 "quoted-printable")
(iso-8859-8 8 "quoted-printable")
(iso-8859-9 8 "quoted-printable")
+ (iso-8859-14 8 "quoted-printable")
+ (iso-8859-15 8 "quoted-printable")
(iso-2022-jp 7 "base64")
+ (iso-2022-jp-3 7 "base64")
(iso-2022-kr 7 "base64")
(euc-kr 8 "base64")
- (cn-gb2312 8 "quoted-printable")
+ (cn-gb 8 "base64")
+ (gb2312 8 "base64")
(cn-big5 8 "base64")
- (gb2312 8 "quoted-printable")
(big5 8 "base64")
+ (shift_jis 8 "base64")
+ (tis-620 8 "base64")
(iso-2022-jp-2 7 "base64")
(iso-2022-int-1 7 "base64")
))
"A string formatted version of mime-transfer-level")
(make-variable-buffer-local 'mime-transfer-level-string)
-(defun mime-make-charset-default-encoding-alist (transfer-level)
- (mapcar (function
- (lambda (charset-type)
- (let ((charset (car charset-type))
- (type (nth 1 charset-type))
- (encoding (nth 2 charset-type))
- )
- (if (<= type transfer-level)
- (cons charset (mime-encoding-name type))
- (cons charset encoding)
- ))))
- mime-charset-type-list))
-
-(defvar mime-edit-charset-default-encoding-alist
- (mime-make-charset-default-encoding-alist mime-transfer-level))
-(make-variable-buffer-local 'mime-edit-charset-default-encoding-alist)
+;;; @@ about content transfer encoding
+(defvar mime-content-transfer-encoding-priority-list
+ '(nil "8bit" "binary"))
;;; @@ about message inserting
;;;
"Xref" "X-UIDL" "X-Filter" "X-Gnus-.*" "X-VM-.*")
"Delete these fields from original message when it is inserted
as message/rfc822 part.
-Each elements are regexp of field-name. [mime-edit.el]")
+Each elements are regexp of field-name.")
(defvar mime-edit-yank-ignored-field-regexp
(concat "^"
;;; @@ about message splitting
;;;
-(defvar mime-edit-split-message t
- "*Split large message if it is non-nil. [mime-edit.el]")
+(defcustom mime-edit-split-message t
+ "*Split large message if it is non-nil."
+ :group 'mime-edit
+ :type 'boolean)
-(defvar mime-edit-message-default-max-lines 1000
- "*Default maximum lines of a message. [mime-edit.el]")
+(defcustom mime-edit-message-default-max-lines 1000
+ "*Default maximum lines of a message."
+ :group 'mime-edit
+ :type 'integer)
-(defvar mime-edit-message-max-lines-alist
+(defcustom mime-edit-message-max-lines-alist
'((news-reply-mode . 500))
"Alist of major-mode vs maximum lines of a message.
If it is not specified for a major-mode,
-`mime-edit-message-default-max-lines' is used. [mime-edit.el]")
+`mime-edit-message-default-max-lines' is used."
+ :group 'mime-edit
+ :type 'list)
(defconst mime-edit-split-ignored-field-regexp
- "\\(^Content-\\|^Subject:\\|^Mime-Version:\\)")
+ "\\(^Content-\\|^Subject:\\|^Mime-Version:\\|^Message-Id:\\)")
-(defvar mime-edit-split-blind-field-regexp
- "\\(^[BDFbdf]cc:\\|^cc:[ \t]*$\\)")
+(defcustom mime-edit-split-blind-field-regexp
+ "\\(^[BDFbdf]cc:\\|^cc:[ \t]*$\\)"
+ "*Regular expression to match field-name to be ignored when split sending."
+ :group 'mime-edit
+ :type 'regexp)
(defvar mime-edit-split-message-sender-alist nil)
(defvar mime-edit-news-reply-mode-server-running nil)
-;;; @@ about PGP
-;;;
-
-(defvar mime-edit-signing-type 'pgp-elkins
- "*PGP signing type (pgp-elkins, pgp-kazu or nil). [mime-edit.el]")
-
-(defvar mime-edit-encrypting-type 'pgp-elkins
- "*PGP encrypting type (pgp-elkins, pgp-kazu or nil). [mime-edit.el]")
-
-
;;; @@ about tag
;;;
;;; @@ optional header fields
;;;
-(defvar mime-edit-insert-x-emacs-field t
- "*If non-nil, insert X-Emacs header field.")
-
-(defvar mime-edit-x-emacs-value
- (if running-xemacs
- (concat emacs-version
+(defvar mime-edit-insert-user-agent-field t
+ "*If non-nil, insert User-Agent header field.")
+
+(defvar mime-edit-user-agent-value
+ (concat (mime-product-name mime-user-interface-product)
+ "/"
+ (mapconcat #'number-to-string
+ (mime-product-version mime-user-interface-product) ".")
+ " ("
+ (mime-product-code-name mime-user-interface-product)
+ ") "
+ (mime-product-name mime-library-product)
+ "/"
+ (mapconcat #'number-to-string
+ (mime-product-version mime-library-product) ".")
+ " ("
+ (mime-product-code-name mime-library-product)
+ ") "
+ (if (fboundp 'apel-version)
+ (concat (apel-version) " "))
+ (if (featurep 'xemacs)
+ (concat (cond ((and (featurep 'chise)
+ (boundp 'xemacs-chise-version))
+ (concat "CHISE-MULE/" xemacs-chise-version))
+ ((featurep 'utf-2000)
+ (concat "UTF-2000-MULE/" utf-2000-version))
+ ((featurep 'mule) "MULE"))
+ " XEmacs"
+ (if (string-match "^[0-9]+\\(\\.[0-9]+\\)" emacs-version)
+ (concat
+ "/"
+ (substring emacs-version 0 (match-end 0))
+ (cond ((and (boundp 'xemacs-betaname)
+ xemacs-betaname)
+ ;; It does not exist in XEmacs
+ ;; versions prior to 20.3.
+ (concat " " xemacs-betaname))
+ ((and (boundp 'emacs-patch-level)
+ emacs-patch-level)
+ ;; It does not exist in FSF Emacs or in
+ ;; XEmacs versions earlier than 21.1.1.
+ (format " (patch %d)" emacs-patch-level))
+ (t ""))
+ " (" xemacs-codename ")"
+ ;; `xemacs-extra-name' has appeared in the
+ ;; development version of XEmacs 21.5-b8.
+ (if (and (boundp 'xemacs-extra-name)
+ (symbol-value 'xemacs-extra-name))
+ (concat " " (symbol-value 'xemacs-extra-name))
+ "")
+ " ("
+ system-configuration ")")
+ " (" emacs-version ")"))
+ (let ((ver (if (string-match "\\.[0-9]+$" emacs-version)
+ (substring emacs-version 0 (match-beginning 0))
+ emacs-version)))
(if (featurep 'mule)
- " with mule"
- " without mule"))
- (let ((ver (if (string-match "\\.[0-9]+$" emacs-version)
- (substring emacs-version 0 (match-beginning 0))
- emacs-version)))
- (if (featurep 'mule)
- (concat "Emacs " ver ", MULE " mule-version)
- ver))))
+ (if (boundp 'enable-multibyte-characters)
+ (concat "Emacs/" ver
+ " (" system-configuration ")"
+ (if enable-multibyte-characters
+ (concat " MULE/" mule-version)
+ " (with unibyte mode)")
+ (if (featurep 'meadow)
+ (let ((mver (Meadow-version)))
+ (if (string-match "^Meadow-" mver)
+ (concat " Meadow/"
+ (substring mver
+ (match-end 0)))
+ ))))
+ (concat "MULE/" mule-version
+ " (based on Emacs " ver ")"))
+ (concat "Emacs/" ver " (" system-configuration ")")))))
+ "Body of User-Agent field.
+If variable `mime-edit-insert-user-agent-field' is not nil, it is
+inserted into message header.")
\f
;;; @ constants
Tspecials means any character that matches with it in header must be quoted.")
(defconst mime-edit-mime-version-value
- (concat "1.0 (generated by " mime-edit-version-name ")")
+ (concat "1.0 (generated by " mime-edit-version ")")
"MIME version number.")
+(defconst mime-edit-mime-version-field-for-message/partial
+ (concat "MIME-Version:"
+ (mime-encode-field-body
+ (concat " 1.0 (split by " mime-edit-version ")\n")
+ "MIME-Version"))
+ "MIME version field for message/partial.")
+
;;; @ keymap and menu
;;;
(defvar mime-edit-mode-flag nil)
(make-variable-buffer-local 'mime-edit-mode-flag)
+(defvar mime-edit-mode-entity-prefix "\C-c\C-x"
+ "Keymap prefix for MIME-Edit mode commands to insert entity or set status.")
+(defvar mime-edit-mode-entity-map (make-sparse-keymap)
+ "Keymap for MIME-Edit mode commands to insert entity or set status.")
+
+(define-key mime-edit-mode-entity-map "\C-t" 'mime-edit-insert-text)
+(define-key mime-edit-mode-entity-map "\C-i" 'mime-edit-insert-file)
+(define-key mime-edit-mode-entity-map "\C-e" 'mime-edit-insert-external)
+(define-key mime-edit-mode-entity-map "\C-v" 'mime-edit-insert-voice)
+(define-key mime-edit-mode-entity-map "\C-y" 'mime-edit-insert-message)
+(define-key mime-edit-mode-entity-map "\C-m" 'mime-edit-insert-mail)
+(define-key mime-edit-mode-entity-map "\C-w" 'mime-edit-insert-signature)
+(define-key mime-edit-mode-entity-map "\C-s" 'mime-edit-insert-signature)
+(define-key mime-edit-mode-entity-map "\C-k" 'mime-edit-insert-key)
+(define-key mime-edit-mode-entity-map "t" 'mime-edit-insert-tag)
+
+(define-key mime-edit-mode-entity-map "7" 'mime-edit-set-transfer-level-7bit)
+(define-key mime-edit-mode-entity-map "8" 'mime-edit-set-transfer-level-8bit)
+(define-key mime-edit-mode-entity-map "/" 'mime-edit-set-split)
+(define-key mime-edit-mode-entity-map "s" 'mime-edit-set-sign)
+(define-key mime-edit-mode-entity-map "v" 'mime-edit-set-sign)
+(define-key mime-edit-mode-entity-map "e" 'mime-edit-set-encrypt)
+(define-key mime-edit-mode-entity-map "h" 'mime-edit-set-encrypt)
+(define-key mime-edit-mode-entity-map "p" 'mime-edit-preview-message)
+(define-key mime-edit-mode-entity-map "\C-z" 'mime-edit-exit)
+(define-key mime-edit-mode-entity-map "?" 'mime-edit-help)
+
+(defvar mime-edit-mode-enclosure-prefix "\C-c\C-m"
+ "Keymap prefix for MIME-Edit mode commands about enclosure.")
+(defvar mime-edit-mode-enclosure-map (make-sparse-keymap)
+ "Keymap for MIME-Edit mode commands about enclosure.")
+
+(define-key mime-edit-mode-enclosure-map
+ "\C-a" 'mime-edit-enclose-alternative-region)
+(define-key mime-edit-mode-enclosure-map
+ "\C-p" 'mime-edit-enclose-parallel-region)
+(define-key mime-edit-mode-enclosure-map
+ "\C-m" 'mime-edit-enclose-mixed-region)
+(define-key mime-edit-mode-enclosure-map
+ "\C-d" 'mime-edit-enclose-digest-region)
+(define-key mime-edit-mode-enclosure-map
+ "\C-s" 'mime-edit-enclose-pgp-signed-region)
+(define-key mime-edit-mode-enclosure-map
+ "\C-e" 'mime-edit-enclose-pgp-encrypted-region)
+(define-key mime-edit-mode-enclosure-map
+ "\C-q" 'mime-edit-enclose-quote-region)
+
(defvar mime-edit-mode-map (make-sparse-keymap)
"Keymap for MIME-Edit mode commands.")
-
-(define-key mime-edit-mode-map
- "\C-c\C-x\C-t" 'mime-edit-insert-text)
-(define-key mime-edit-mode-map
- "\C-c\C-x\C-i" 'mime-edit-insert-file)
-(define-key mime-edit-mode-map
- "\C-c\C-x\C-e" 'mime-edit-insert-external)
-(define-key mime-edit-mode-map
- "\C-c\C-x\C-v" 'mime-edit-insert-voice)
-(define-key mime-edit-mode-map
- "\C-c\C-x\C-y" 'mime-edit-insert-message)
-(define-key mime-edit-mode-map
- "\C-c\C-x\C-m" 'mime-edit-insert-mail)
-(define-key mime-edit-mode-map
- "\C-c\C-x\C-w" 'mime-edit-insert-signature)
-(define-key mime-edit-mode-map
- "\C-c\C-x\C-s" 'mime-edit-insert-signature)
-(define-key mime-edit-mode-map
- "\C-c\C-x\C-k" 'mime-edit-insert-key)
-(define-key mime-edit-mode-map
- "\C-c\C-xt" 'mime-edit-insert-tag)
-
-(define-key mime-edit-mode-map
- "\C-c\C-m\C-a" 'mime-edit-enclose-alternative-region)
-(define-key mime-edit-mode-map
- "\C-c\C-m\C-p" 'mime-edit-enclose-parallel-region)
(define-key mime-edit-mode-map
- "\C-c\C-m\C-m" 'mime-edit-enclose-mixed-region)
+ mime-edit-mode-entity-prefix mime-edit-mode-entity-map)
(define-key mime-edit-mode-map
- "\C-c\C-m\C-d" 'mime-edit-enclose-digest-region)
-(define-key mime-edit-mode-map
- "\C-c\C-m\C-s" 'mime-edit-enclose-signed-region)
-(define-key mime-edit-mode-map
- "\C-c\C-m\C-e" 'mime-edit-enclose-encrypted-region)
-(define-key mime-edit-mode-map
- "\C-c\C-m\C-q" 'mime-edit-enclose-quote-region)
-
-(define-key mime-edit-mode-map
- "\C-c\C-x7" 'mime-edit-set-transfer-level-7bit)
-(define-key mime-edit-mode-map
- "\C-c\C-x8" 'mime-edit-set-transfer-level-8bit)
-(define-key mime-edit-mode-map
- "\C-c\C-x/" 'mime-edit-set-split)
-(define-key mime-edit-mode-map
- "\C-c\C-xs" 'mime-edit-set-sign)
-(define-key mime-edit-mode-map
- "\C-c\C-xv" 'mime-edit-set-sign)
-(define-key mime-edit-mode-map
- "\C-c\C-xe" 'mime-edit-set-encrypt)
-(define-key mime-edit-mode-map
- "\C-c\C-xh" 'mime-edit-set-encrypt)
-(define-key mime-edit-mode-map
- "\C-c\C-x\C-p" 'mime-edit-preview-message)
-(define-key mime-edit-mode-map
- "\C-c\C-x\C-z" 'mime-edit-exit)
-(define-key mime-edit-mode-map
- "\C-c\C-x?" 'mime-edit-help)
+ mime-edit-mode-enclosure-prefix mime-edit-mode-enclosure-map)
(defconst mime-edit-menu-title "MIME-Edit")
(parallel "Enclose as parallel" mime-edit-enclose-parallel-region)
(mixed "Enclose as serial" mime-edit-enclose-mixed-region)
(digest "Enclose as digest" mime-edit-enclose-digest-region)
- (signed "Enclose as signed" mime-edit-enclose-signed-region)
- (encrypted "Enclose as encrypted" mime-edit-enclose-encrypted-region)
+ (signed "Enclose as signed" mime-edit-enclose-pgp-signed-region)
+ (encrypted "Enclose as encrypted" mime-edit-enclose-pgp-encrypted-region)
(quote "Verbatim region" mime-edit-enclose-quote-region)
(key "Insert Public Key" mime-edit-insert-key)
- (split "About split" mime-edit-set-split)
- (sign "About sign" mime-edit-set-sign)
- (encrypt "About encryption" mime-edit-set-encrypt)
+ (split "Set splitting" mime-edit-set-split)
+ (sign "PGP sign" mime-edit-set-sign)
+ (encrypt "PGP encrypt" mime-edit-set-encrypt)
(preview "Preview Message" mime-edit-preview-message)
(level "Toggle transfer-level" mime-edit-toggle-transfer-level)
)
"MIME-edit menubar entry.")
-(cond (running-xemacs
+(cond ((featurep 'xemacs)
;; modified by Pekka Marjola <pema@iki.fi>
;; 1995/9/5 (c.f. [tm-en:69])
(defun mime-edit-define-menu-for-xemacs ()
- "Define menu for Emacs 19."
+ "Define menu for XEmacs."
(cond ((featurep 'menubar)
(make-local-variable 'current-menubar)
(set-buffer-menubar current-menubar)
))
mime-edit-menu-list)))
)))
-
+
;; modified by Steven L. Baur <steve@miranova.com>
;; 1995/12/6 (c.f. [tm-en:209])
(or (boundp 'mime-edit-popup-menu-for-xemacs)
;;; @ functions
;;;
+(defvar mime-edit-touched-flag nil)
+
;;;###autoload
(defun mime-edit-mode ()
"MIME minor mode for editing the tagged MIME message.
\\[mime-edit-insert-tag] insert a new MIME tag.
\[make enclosure (maybe multipart)\]
-\\[mime-edit-enclose-alternative-region] enclose as multipart/alternative.
-\\[mime-edit-enclose-parallel-region] enclose as multipart/parallel.
-\\[mime-edit-enclose-mixed-region] enclose as multipart/mixed.
-\\[mime-edit-enclose-digest-region] enclose as multipart/digest.
-\\[mime-edit-enclose-signed-region] enclose as PGP signed.
-\\[mime-edit-enclose-encrypted-region] enclose as PGP encrypted.
-\\[mime-edit-enclose-quote-region] enclose as verbose mode (to avoid to expand tags)
+\\[mime-edit-enclose-alternative-region] enclose as multipart/alternative.
+\\[mime-edit-enclose-parallel-region] enclose as multipart/parallel.
+\\[mime-edit-enclose-mixed-region] enclose as multipart/mixed.
+\\[mime-edit-enclose-digest-region] enclose as multipart/digest.
+\\[mime-edit-enclose-pgp-signed-region] enclose as PGP signed.
+\\[mime-edit-enclose-pgp-encrypted-region] enclose as PGP encrypted.
+\\[mime-edit-enclose-quote-region] enclose as verbose mode
+ (to avoid to expand tags)
\[other commands\]
\\[mime-edit-set-transfer-level-7bit] set transfer-level as 7.
\\[mime-edit-set-transfer-level-8bit] set transfer-level as 8.
-\\[mime-edit-set-split] set message splitting mode.
-\\[mime-edit-set-sign] set PGP-sign mode.
-\\[mime-edit-set-encrypt] set PGP-encryption mode.
-\\[mime-edit-preview-message] preview editing MIME message.
-\\[mime-edit-exit] exit and translate into a MIME compliant message.
-\\[mime-edit-help] show this help.
-\\[mime-edit-maybe-translate] exit and translate if in MIME mode, then split.
+\\[mime-edit-set-split] set message splitting mode.
+\\[mime-edit-set-sign] set PGP-sign mode.
+\\[mime-edit-set-encrypt] set PGP-encryption mode.
+\\[mime-edit-preview-message] preview editing MIME message.
+\\[mime-edit-exit] exit and translate into a MIME
+ compliant message.
+\\[mime-edit-help] show this help.
+\\[mime-edit-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.
(interactive)
(if mime-edit-mode-flag
(mime-edit-exit)
- (if (and (boundp 'mime-edit-touched-flag)
- mime-edit-touched-flag)
+ (if mime-edit-touched-flag
(mime-edit-again)
(make-local-variable 'mime-edit-touched-flag)
(setq mime-edit-touched-flag t)
)))
-(cond (running-xemacs
+(cond ((featurep 'xemacs)
(add-minor-mode 'mime-edit-mode-flag
'((" MIME-Edit " mime-transfer-level-string))
mime-edit-mode-map
(if mime-edit-mode-flag
(error "You are already editing a MIME message.")
(setq mime-edit-mode-flag t)
-
+
;; Set transfer level into mode line
;;
(setq mime-transfer-level-string
(mime-encoding-name mime-transfer-level 'not-omit))
(force-mode-line-update)
-
+
;; Define menu for XEmacs.
- (if running-xemacs
+ (if (featurep 'xemacs)
(mime-edit-define-menu-for-xemacs)
)
-
+
(enable-invisible)
-
- ;; I don't care about saving these.
+
+ (make-local-variable 'paragraph-start)
(setq paragraph-start
(regexp-or mime-edit-single-part-tag-regexp
paragraph-start))
+ (make-local-variable 'paragraph-separate)
(setq paragraph-separate
(regexp-or mime-edit-single-part-tag-regexp
paragraph-separate))
(run-hooks 'mime-edit-mode-hook)
(message
+ "%s"
(substitute-command-keys
"Type \\[mime-edit-exit] to exit MIME mode, and type \\[mime-edit-help] to get help."))
))
(mime-edit-translate-buffer)))
;; Restore previous state.
(setq mime-edit-mode-flag nil)
- (if (and running-xemacs
+ (if (and (featurep 'xemacs)
(featurep 'menubar))
(delete-menu-item (list mime-edit-menu-title))
)
(princ (documentation 'mime-edit-mode))
(print-help-return-message)))
-(defun mime-edit-insert-text ()
+(defun mime-edit-insert-text (&optional subtype)
"Insert a text message.
-Charset is automatically obtained from the `charsets-mime-charset-alist'."
+Charset is automatically obtained from the `charsets-mime-charset-alist'.
+If optional argument SUBTYPE is not nil, text/SUBTYPE tag is inserted."
(interactive)
- (let ((ret (mime-edit-insert-tag "text" nil nil)))
- (if ret
- (progn
- (if (looking-at mime-edit-single-part-tag-regexp)
- (progn
- ;; Make a space between the following message.
- (insert "\n")
- (forward-char -1)
- ))
- (if (and (member (second ret) '("enriched" "richtext"))
- (fboundp 'enriched-mode)
- )
- (enriched-mode t)
- (if (boundp 'enriched-mode)
- (enriched-mode nil)
- ))))))
+ (let ((ret (mime-edit-insert-tag "text" subtype nil)))
+ (when ret
+ (if (looking-at mime-edit-single-part-tag-regexp)
+ (progn
+ ;; Make a space between the following message.
+ (insert "\n")
+ (forward-char -1)
+ ))
+ (if (and (member (cadr ret) '("enriched"))
+ (fboundp 'enriched-mode))
+ (enriched-mode t)
+ (if (boundp 'enriched-mode)
+ (enriched-mode -1)
+ ))
+ )))
(defun mime-edit-insert-file (file &optional verbose)
"Insert a message from a file."
(disposition-type (nth 4 guess))
(disposition-params (nth 5 guess))
)
- (if verbose
- (setq type (mime-prompt-for-type type)
- subtype (mime-prompt-for-subtype type subtype)
- ))
(if (or (interactive-p) verbose)
- (setq encoding (mime-prompt-for-encoding encoding))
- )
+ (setq type (mime-prompt-for-type type)
+ subtype (mime-prompt-for-subtype type subtype)
+ encoding (mime-prompt-for-encoding encoding)))
(if (or (consp parameters) (stringp disposition-type))
(let ((rest parameters) cell attribute value)
(setq parameters "")
(let ((encoding
(completing-read
"What transfer encoding: "
- mime-file-encoding-method-alist nil t nil)))
+ (mime-encoding-alist) nil t nil)))
(mime-edit-insert-tag "audio" "basic" nil)
(mime-edit-define-encoding encoding)
(save-restriction
(let ((signature-insert-hook
(function
(lambda ()
- (apply (function mime-edit-insert-tag)
- (mime-find-file-type signature-file-name))
+ (let ((items (mime-find-file-type signature-file-name)))
+ (apply (function mime-edit-insert-tag)
+ (car items) (cadr items) (list (caddr items))))
)))
)
(insert-signature arg)
(t
(goto-char (point-max))
))
- ;; Then search for the beginning.
+ ;; Then search for the beginning.
(re-search-backward mime-edit-end-tag-regexp nil t)
(or (looking-at mime-edit-beginning-tag-regexp)
;; Restore previous point.
(defun mime-edit-content-end ()
"Return the point of the end of content."
(save-excursion
- (let ((beg (point)))
- (if (mime-edit-goto-tag)
- (let ((top (point)))
- (goto-char (match-end 0))
- (if (invisible-p (point))
- (next-visible-point (point))
- ;; Move to the end of this text.
- (if (re-search-forward mime-edit-tag-regexp nil 'move)
- ;; Don't forget a multiline tag.
- (goto-char (match-beginning 0))
- )
- (point)
- ))
- ;; Assume the message begins with text/plain.
- (goto-char (mime-edit-content-beginning))
- (if (re-search-forward mime-edit-tag-regexp nil 'move)
- ;; Don't forget a multiline tag.
- (goto-char (match-beginning 0)))
- (point))
- )))
+ (if (mime-edit-goto-tag)
+ (progn
+ (goto-char (match-end 0))
+ (if (invisible-p (point))
+ (next-visible-point (point))
+ ;; Move to the end of this text.
+ (if (re-search-forward mime-edit-tag-regexp nil 'move)
+ ;; Don't forget a multiline tag.
+ (goto-char (match-beginning 0))
+ )
+ (point)
+ ))
+ ;; Assume the message begins with text/plain.
+ (goto-char (mime-edit-content-beginning))
+ (if (re-search-forward mime-edit-tag-regexp nil 'move)
+ ;; Don't forget a multiline tag.
+ (goto-char (match-beginning 0)))
+ (point))
+ ))
(defun mime-edit-define-charset (charset)
"Set charset of current tag to CHARSET."
(mime-create-tag
(mime-edit-set-parameter
(mime-edit-get-contype tag)
- "charset" (upcase (symbol-name charset)))
+ "charset"
+ (let ((comment (get charset 'mime-charset-comment)))
+ (if comment
+ (concat (upcase (symbol-name charset)) " (" comment ")")
+ (upcase (symbol-name charset)))))
(mime-edit-get-encoding tag)))
))))
;; Change value
(concat (substring ctype 0 (match-beginning 1))
parameter "=" value
- (substring contype (match-end 1))
+ (substring ctype (match-end 1))
opt-fields)
(concat ctype "; " parameter "=" value opt-fields)
)))
(defun mime-prompt-for-parameter (parameter)
"Ask for PARAMETER.
-Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))."
+Parameter must be '(PROMPT CHOICE1 (CHOICE2...))."
(let* ((prompt (car parameter))
(choices (mapcar (function
(lambda (e)
))
(defun mime-prompt-for-encoding (default)
- "Ask for Content-Transfer-Encoding. [mime-edit.el]"
+ "Ask for Content-Transfer-Encoding."
(let (encoding)
(while (string=
(setq encoding
(completing-read
"What transfer encoding: "
- mime-file-encoding-method-alist nil t default)
+ (mime-encoding-alist) nil t default)
)
""))
encoding))
(defun mime-edit-translate-header ()
"Encode the message header into network representation."
- (eword-encode-header 'code-conversion)
- (run-hooks 'mime-edit-translate-header-hook)
- )
+ (mime-encode-header-in-buffer 'code-conversion)
+ (run-hooks 'mime-edit-translate-header-hook))
(defun mime-edit-translate-buffer ()
"Encode the tagged MIME message in current buffer in MIME compliant message."
(interactive)
+ (undo-boundary)
(if (catch 'mime-edit-error
(save-excursion
(run-hooks 'mime-edit-translate-buffer-hook)
(let ((bb (match-beginning 0))
(be (match-end 0))
(type (buffer-substring (match-beginning 1)(match-end 1)))
- end-exp eb ee)
+ end-exp eb)
(setq end-exp (format "--}-<<%s>>\n" type))
(widen)
(if (re-search-forward end-exp nil t)
- (progn
- (setq eb (match-beginning 0))
- (setq ee (match-end 0))
- )
+ (setq eb (match-beginning 0))
(setq eb (point-max))
- (setq ee (point-max))
)
(narrow-to-region be eb)
(goto-char be)
(if (re-search-forward mime-edit-multipart-beginning-regexp nil t)
- (let (ret)
+ (progn
(narrow-to-region (match-beginning 0)(point-max))
(mime-edit-find-inmost)
)
)
(delete-region beg end)
(or (looking-at mime-edit-beginning-tag-regexp)
+ (looking-at mime-edit-multipart-end-regexp)
(eobp)
(insert (concat (mime-make-text-tag) "\n"))
)))
(cond ((string-equal type "quote")
(mime-edit-enquote-region bb eb)
)
- ((string-equal type "signed")
- (cond ((eq mime-edit-signing-type 'pgp-elkins)
- (mime-edit-sign-pgp-elkins bb eb boundary)
- )
- ((eq mime-edit-signing-type 'pgp-kazu)
- (mime-edit-sign-pgp-kazu bb eb boundary)
- ))
+ ((string-equal type "pgp-signed")
+ (mime-edit-sign-pgp-mime bb eb boundary)
+ )
+ ((string-equal type "pgp-encrypted")
+ (mime-edit-encrypt-pgp-mime bb eb boundary)
+ )
+ ((string-equal type "kazu-signed")
+ (mime-edit-sign-pgp-kazu bb eb boundary)
+ )
+ ((string-equal type "kazu-encrypted")
+ (mime-edit-encrypt-pgp-kazu bb eb boundary)
+ )
+ ((string-equal type "smime-signed")
+ (mime-edit-sign-smime bb eb boundary)
+ )
+ ((string-equal type "smime-encrypted")
+ (mime-edit-encrypt-smime bb eb boundary)
)
- ((string-equal type "encrypted")
- (cond ((eq mime-edit-encrypting-type 'pgp-elkins)
- (mime-edit-encrypt-pgp-elkins bb eb boundary)
- )
- ((eq mime-edit-encrypting-type 'pgp-kazu)
- (mime-edit-encrypt-pgp-kazu bb eb boundary)
- )))
(t
(setq boundary
(nth 2 (mime-edit-translate-region bb eb
(replace-match (concat "-" (substring tag 2)))
)))))
-(defun mime-edit-sign-pgp-elkins (beg end boundary)
+(defvar mime-edit-pgp-user-id nil)
+
+(defun mime-edit-delete-trailing-whitespace ()
+ (save-match-data
+ (save-excursion
+ (goto-char (point-min))
+ (while (re-search-forward "[ \t]+$" nil t)
+ (delete-region (match-beginning 0) (match-end 0))))))
+
+(defun mime-edit-sign-pgp-mime (beg end boundary)
(save-excursion
(save-restriction
- (narrow-to-region beg end)
- (let* ((ret
- (mime-edit-translate-region beg end boundary))
+ (let* ((from (std11-field-body "From" mail-header-separator))
+ (ret (progn
+ (narrow-to-region beg end)
+ (mime-edit-translate-region beg end boundary)))
(ctype (car ret))
(encoding (nth 1 ret))
- (parts (nth 3 ret))
(pgp-boundary (concat "pgp-sign-" boundary))
- )
+ micalg)
+ (mime-edit-delete-trailing-whitespace) ; RFC3156
(goto-char beg)
(insert (format "Content-Type: %s\n" ctype))
(if encoding
(insert (format "Content-Transfer-Encoding: %s\n" encoding))
)
(insert "\n")
- (or (funcall (pgp-function 'mime-sign)
- (point-min)(point-max) nil nil pgp-boundary)
+ (or (let ((pgg-default-user-id
+ (or mime-edit-pgp-user-id
+ (if from
+ (nth 1 (std11-extract-address-components from))
+ pgg-default-user-id)))
+ (pgg-text-mode t))
+ (pgg-sign-region (point-min)(point-max)))
(throw 'mime-edit-error 'pgp-error)
)
+ (setq micalg
+ (cdr (assq 'hash-algorithm
+ (cdar (with-current-buffer pgg-output-buffer
+ (pgg-parse-armor-region
+ (point-min)(point-max))))))
+ micalg
+ (if micalg
+ (concat "; micalg=pgp-" (downcase (symbol-name micalg)))
+ ""))
+ (goto-char beg)
+ (insert (format "--[[multipart/signed;
+ boundary=\"%s\"%s;
+ protocol=\"application/pgp-signature\"][7bit]]
+--%s
+" pgp-boundary micalg pgp-boundary))
+ (goto-char (point-max))
+ (insert (format "\n--%s
+Content-Type: application/pgp-signature
+Content-Transfer-Encoding: 7bit
+
+" pgp-boundary))
+ (insert-buffer-substring pgg-output-buffer)
+ (goto-char (point-max))
+ (insert (format "\n--%s--\n" pgp-boundary))
))))
(defvar mime-edit-encrypt-recipient-fields-list '("To" "cc"))
(vector from recipients header)
))
-(defun mime-edit-encrypt-pgp-elkins (beg end boundary)
+(defun mime-edit-encrypt-pgp-mime (beg end boundary)
(save-excursion
(save-restriction
(let (from recipients header)
- (let ((ret (mime-edit-make-encrypt-recipient-header)))
- (setq from (aref ret 0)
- recipients (aref ret 1)
- header (aref ret 2))
+ (let ((ret (mime-edit-make-encrypt-recipient-header)))
+ (setq from (aref ret 0)
+ recipients (aref ret 1)
+ header (aref ret 2))
)
- (narrow-to-region beg end)
- (let* ((ret
- (mime-edit-translate-region beg end boundary))
- (ctype (car ret))
- (encoding (nth 1 ret))
- (parts (nth 3 ret))
- (pgp-boundary (concat "pgp-" boundary))
- )
- (goto-char beg)
- (insert header)
- (insert (format "Content-Type: %s\n" ctype))
- (if encoding
- (insert (format "Content-Transfer-Encoding: %s\n" encoding))
- )
- (insert "\n")
- (or (funcall (pgp-function 'encrypt)
- recipients (point-min) (point-max) from)
+ (narrow-to-region beg end)
+ (let* ((ret
+ (mime-edit-translate-region beg end boundary))
+ (ctype (car ret))
+ (encoding (nth 1 ret))
+ (pgp-boundary (concat "pgp-" boundary)))
+ (goto-char beg)
+ (insert header)
+ (insert (format "Content-Type: %s\n" ctype))
+ (if encoding
+ (insert (format "Content-Transfer-Encoding: %s\n" encoding))
+ )
+ (insert "\n")
+ (mime-encode-header-in-buffer)
+ (or (let ((pgg-default-user-id
+ (or mime-edit-pgp-user-id
+ (if from
+ (nth 1 (std11-extract-address-components from))
+ pgg-default-user-id)))
+ (pgg-text-mode t))
+ (pgg-encrypt-region
+ (point-min) (point-max)
+ (mapcar (lambda (recipient)
+ (nth 1 (std11-extract-address-components
+ recipient)))
+ (split-string recipients
+ "\\([ \t\n]*,[ \t\n]*\\)+")))
+ )
(throw 'mime-edit-error 'pgp-error)
)
+ (delete-region (point-min)(point-max))
(goto-char beg)
(insert (format "--[[multipart/encrypted;
boundary=\"%s\";
--%s
Content-Type: application/pgp-encrypted
+Version: 1
--%s
Content-Type: application/octet-stream
Content-Transfer-Encoding: 7bit
" pgp-boundary pgp-boundary pgp-boundary))
+ (insert-buffer-substring pgg-output-buffer)
(goto-char (point-max))
(insert (format "\n--%s--\n" pgp-boundary))
)))))
(let* ((ret
(mime-edit-translate-region beg end boundary))
(ctype (car ret))
- (encoding (nth 1 ret))
- (parts (nth 3 ret))
- )
+ (encoding (nth 1 ret)))
(goto-char beg)
(insert (format "Content-Type: %s\n" ctype))
(if encoding
(insert (format "Content-Transfer-Encoding: %s\n" encoding))
)
(insert "\n")
- (or (as-binary-process
- (funcall (pgp-function 'traditional-sign)
- beg (point-max)))
+ (or (pgg-sign-region beg (point-max) 'clearsign)
(throw 'mime-edit-error 'pgp-error)
)
(goto-char beg)
(defun mime-edit-encrypt-pgp-kazu (beg end boundary)
(save-excursion
- (let (from recipients header)
+ (let (recipients header)
(let ((ret (mime-edit-make-encrypt-recipient-header)))
- (setq from (aref ret 0)
- recipients (aref ret 1)
+ (setq recipients (aref ret 1)
header (aref ret 2))
)
(save-restriction
(let* ((ret
(mime-edit-translate-region beg end boundary))
(ctype (car ret))
- (encoding (nth 1 ret))
- (parts (nth 3 ret))
- )
+ (encoding (nth 1 ret)))
(goto-char beg)
(insert header)
(insert (format "Content-Type: %s\n" ctype))
(insert (format "Content-Transfer-Encoding: %s\n" encoding))
)
(insert "\n")
- (or (as-binary-process
- (funcall (pgp-function 'encrypt)
- recipients beg (point-max) nil 'maybe)
- )
+ (or (pgg-encrypt-region beg (point-max) recipients)
(throw 'mime-edit-error 'pgp-error)
)
(goto-char beg)
))
)))
+(defun mime-edit-sign-smime (beg end boundary)
+ (save-excursion
+ (save-restriction
+ (let* ((ret (progn
+ (narrow-to-region beg end)
+ (mime-edit-translate-region beg end boundary)))
+ (ctype (car ret))
+ (encoding (nth 1 ret))
+ (smime-boundary (concat "smime-sign-" boundary)))
+ (goto-char beg)
+ (insert (format "Content-Type: %s\n" ctype))
+ (if encoding
+ (insert (format "Content-Transfer-Encoding: %s\n" encoding))
+ )
+ (insert "\n")
+ (let (buffer-undo-list)
+ (goto-char (point-min))
+ (while (progn (end-of-line) (not (eobp)))
+ (insert "\r")
+ (forward-line 1))
+ (or (prog1 (smime-sign-region (point-min)(point-max))
+ (push nil buffer-undo-list)
+ (ignore-errors (undo)))
+ (throw 'mime-edit-error 'pgp-error)
+ ))
+ (goto-char beg)
+ (insert (format "--[[multipart/signed;
+ boundary=\"%s\"; micalg=sha1;
+ protocol=\"application/pkcs7-signature\"][7bit]]
+--%s
+" smime-boundary smime-boundary))
+ (goto-char (point-max))
+ (insert (format "\n--%s
+Content-Type: application/pkcs7-signature; name=\"smime.p7s\"
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment; filename=\"smime.p7s\"
+Content-Description: S/MIME Cryptographic Signature
+
+" smime-boundary))
+ (insert-buffer-substring smime-output-buffer)
+ (goto-char (point-max))
+ (insert (format "\n--%s--\n" smime-boundary))
+ ))))
+
+(defun mime-edit-encrypt-smime (beg end boundary)
+ (save-excursion
+ (save-restriction
+ (let* ((ret (progn
+ (narrow-to-region beg end)
+ (mime-edit-translate-region beg end boundary)))
+ (ctype (car ret))
+ (encoding (nth 1 ret)))
+ (goto-char beg)
+ (insert (format "Content-Type: %s\n" ctype))
+ (if encoding
+ (insert (format "Content-Transfer-Encoding: %s\n" encoding))
+ )
+ (insert "\n")
+ (goto-char (point-min))
+ (while (progn (end-of-line) (not (eobp)))
+ (insert "\r")
+ (forward-line 1))
+ (or (smime-encrypt-region (point-min)(point-max))
+ (throw 'mime-edit-error 'pgp-error)
+ )
+ (delete-region (point-min)(point-max))
+ (insert "--[[application/pkcs7-mime; name=\"smime.p7m\"
+Content-Disposition: attachment; filename=\"smime.p7m\"
+Content-Description: S/MIME Encrypted Message][base64]]\n")
+ (insert-buffer-substring smime-output-buffer)
+ ))))
+
(defsubst replace-space-with-underline (str)
(mapconcat (function
(lambda (arg)
(let ((contype (car ret)) ;Content-Type
(encoding (nth 1 ret)) ;Content-Transfer-Encoding
)
- ;; Insert X-Emacs field
- (and mime-edit-insert-x-emacs-field
- (or (mail-position-on-field "X-Emacs")
- (insert mime-edit-x-emacs-value)
+ ;; Insert User-Agent field
+ (and mime-edit-insert-user-agent-field
+ (or (mail-position-on-field "User-Agent")
+ (insert mime-edit-user-agent-value)
))
;; Make primary MIME headers.
- (or (mail-position-on-field "Mime-Version")
+ (or (mail-position-on-field "MIME-Version")
(insert mime-edit-mime-version-value))
;; Remove old Content-Type and other fields.
(save-restriction
(insert encoding)))
))))
-(defun mime-edit-translate-single-part-tag (&optional prefix)
+(defun mime-edit-translate-single-part-tag (boundary &optional prefix)
+ "Translate single-part-tag to MIME header."
(if (re-search-forward mime-edit-single-part-tag-regexp nil t)
(let* ((beg (match-beginning 0))
(end (match-end 0))
- (tag (buffer-substring beg end))
- )
+ (tag (buffer-substring beg end)))
(delete-region beg end)
- (setq contype (mime-edit-get-contype tag))
- (setq encoding (mime-edit-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)))
+ (let ((contype (mime-edit-get-contype tag))
+ (encoding (mime-edit-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-header-in-buffer))
+ (cons (and contype
+ (downcase contype))
+ (and encoding
+ (downcase encoding))))
+ )))
(defun mime-edit-translate-region (beg end &optional boundary multipart)
(or boundary
(t
;; It's a multipart message.
(goto-char (point-min))
- (and (mime-edit-translate-single-part-tag)
- (while (mime-edit-translate-single-part-tag "\n"))
- )
- ;; Define Content-Type as "multipart/mixed".
- (setq contype
- (concat "multipart/mixed;\n boundary=\"" boundary "\""))
- ;; Content-Transfer-Encoding must be "7bit".
- ;; The following encoding can be `nil', but is
- ;; specified as is since there is no way that a user
- ;; specifies it.
- (setq encoding "7bit")
- ;; Insert the trailer.
- (goto-char (point-max))
- (insert "\n--" boundary "--\n")
- ))
- (list contype encoding boundary nparts)
- ))))
+ (let ((prio mime-content-transfer-encoding-priority-list)
+ part-info nprio)
+ (when (setq part-info
+ (mime-edit-translate-single-part-tag boundary))
+ (and (setq nprio (member (cdr part-info) prio))
+ (setq prio nprio))
+ (while (setq part-info
+ (mime-edit-translate-single-part-tag boundary "\n"))
+ (and (setq nprio (member (cdr part-info) prio))
+ (setq prio nprio))))
+ ;; Define Content-Type as "multipart/mixed".
+ (setq contype
+ (concat "multipart/mixed;\n boundary=\"" boundary "\""))
+ (setq encoding (car prio))
+ ;; Insert the trailer.
+ (goto-char (point-max))
+ (insert "\n--" boundary "--\n")
+ )))
+ (list contype encoding boundary nparts)
+ ))))
(defun mime-edit-normalize-body ()
"Normalize the body part by inserting appropriate message tags."
(intern (downcase charset))
(mime-edit-choose-charset)))
(mime-edit-define-charset charset)
- (cond ((string-equal contype "text/x-rot13-47")
+ (cond ((string-equal contype "text/x-rot13-47-48")
(save-excursion
(forward-line)
- (set-mark (point))
- (goto-char (mime-edit-content-end))
- (tm:caesar-region)
+ (mule-caesar-region (point) (mime-edit-content-end))
))
((string-equal contype "text/enriched")
(save-excursion
;; (point)
;; 'hard t)))
;; End patch for hard newlines
- (enriched-encode beg end)
+ (enriched-encode beg end nil)
(goto-char beg)
(if (search-forward "\n\n")
(delete-region beg (match-end 0))
;; Define encoding and encode text if necessary.
(or encoding ;Encoding is not specified.
(let* ((encoding
- (cdr
- (assq charset
- mime-edit-charset-default-encoding-alist)
- ))
- (beg (mime-edit-content-beginning))
- )
+ (let (bits conv)
+ (let ((ret (cdr (assq charset mime-charset-type-list))))
+ (if ret
+ (setq bits (car ret)
+ conv (nth 1 ret))
+ (setq bits 8
+ conv "quoted-printable")))
+ (if (<= bits mime-transfer-level)
+ (mime-encoding-name bits)
+ conv)))
+ (beg (mime-edit-content-beginning)))
(encode-mime-charset-region beg (mime-edit-content-end)
charset)
- (mime-encode-region beg (mime-edit-content-end) encoding)
+ ;; Protect "From " in beginning of line
+ (save-restriction
+ (narrow-to-region beg (mime-edit-content-end))
+ (goto-char beg)
+ (let (case-fold-search)
+ (if (re-search-forward "^From " nil t)
+ (unless encoding
+ (if (memq charset '(iso-2022-jp
+ iso-2022-jp-2
+ iso-2022-int-1
+ x-ctext))
+ (while (progn
+ (replace-match "\e(BFrom ")
+ (re-search-forward "^From " nil t)
+ ))
+ (setq encoding "quoted-printable")
+ )))))
+ ;; canonicalize line break code
+ (or (member encoding '(nil "7bit" "8bit" "quoted-printable"))
+ (save-restriction
+ (narrow-to-region beg (mime-edit-content-end))
+ (goto-char beg)
+ (while (re-search-forward "\\(\\=\\|[^\r]\\)\n" nil t)
+ ;; In a certain period, `replace-match' with "\\N"
+ ;; converted 8-bit characters into multibyte string,
+ ;; but it has been fixed at 2004-01-15.
+ ;;(replace-match "\\1\r\n"))))
+ (backward-char 1)
+ (insert "\r")
+ (forward-char 1))))
+ (goto-char beg)
+ (mime-encode-region beg (mime-edit-content-end)
+ (or encoding "7bit"))
(mime-edit-define-encoding encoding)
))
(goto-char (mime-edit-content-end))
;; encoded.
(let* ((encoding "base64") ;Encode in BASE64 by default.
(beg (mime-edit-content-beginning))
- (end (mime-edit-content-end))
- (body (buffer-substring beg end))
- )
+ (end (mime-edit-content-end)))
(mime-encode-region beg end encoding)
(mime-edit-define-encoding encoding))
(forward-line 1)
(goto-char (point-min))
(while (re-search-forward regexp nil t)
(delete-region (match-beginning 0)
- (progn (forward-line 1) (point)))
- )))
+ (1+ (std11-field-end))))))
\f
;;;
(defun mime-edit-voice-recorder-for-sun (encoding)
"Record voice in a buffer using Sun audio device,
-and insert data encoded as ENCODING. [mime-edit.el]"
+and insert data encoded as ENCODING."
(message "Start the recording on %s. Type C-g to finish the recording..."
(system-name))
(mime-insert-encoded-file "/dev/audio" encoding)
;;; @ multipart enclosure
;;;
-(defun mime-edit-enclose-region (type beg end)
+(defun mime-edit-enclose-region-internal (type beg end)
(save-excursion
(goto-char beg)
- (let ((current (point)))
- (save-restriction
- (narrow-to-region beg end)
- (insert (format "--<<%s>>-{\n" type))
- (goto-char (point-max))
- (insert (format "--}-<<%s>>\n" type))
- (goto-char (point-max))
+ (save-restriction
+ (narrow-to-region beg end)
+ (insert (format "--<<%s>>-{\n" type))
+ (goto-char (point-max))
+ (insert (format "--}-<<%s>>\n" type))
+ (goto-char (point-max))
+ )
+ (or (looking-at mime-edit-beginning-tag-regexp)
+ (eobp)
+ (insert (mime-make-text-tag) "\n")
)
- (or (looking-at mime-edit-beginning-tag-regexp)
- (eobp)
- (insert (mime-make-text-tag) "\n")
- )
- )))
+ ))
(defun mime-edit-enclose-quote-region (beg end)
(interactive "*r")
- (mime-edit-enclose-region "quote" beg end)
+ (mime-edit-enclose-region-internal 'quote beg end)
)
(defun mime-edit-enclose-mixed-region (beg end)
(interactive "*r")
- (mime-edit-enclose-region "mixed" beg end)
+ (mime-edit-enclose-region-internal 'mixed beg end)
)
(defun mime-edit-enclose-parallel-region (beg end)
(interactive "*r")
- (mime-edit-enclose-region "parallel" beg end)
+ (mime-edit-enclose-region-internal 'parallel beg end)
)
(defun mime-edit-enclose-digest-region (beg end)
(interactive "*r")
- (mime-edit-enclose-region "digest" beg end)
+ (mime-edit-enclose-region-internal 'digest beg end)
)
(defun mime-edit-enclose-alternative-region (beg end)
(interactive "*r")
- (mime-edit-enclose-region "alternative" beg end)
+ (mime-edit-enclose-region-internal 'alternative beg end)
)
-(defun mime-edit-enclose-signed-region (beg end)
+(defun mime-edit-enclose-pgp-signed-region (beg end)
(interactive "*r")
- (if mime-edit-signing-type
- (mime-edit-enclose-region "signed" beg end)
- (message "Please specify signing type.")
- ))
+ (mime-edit-enclose-region-internal 'pgp-signed beg end)
+ )
-(defun mime-edit-enclose-encrypted-region (beg end)
+(defun mime-edit-enclose-pgp-encrypted-region (beg end)
(interactive "*r")
- (if mime-edit-signing-type
- (mime-edit-enclose-region "encrypted" beg end)
- (message "Please specify encrypting type.")
- ))
+ (mime-edit-enclose-region-internal 'pgp-encrypted beg end)
+ )
+
+(defun mime-edit-enclose-kazu-signed-region (beg end)
+ (interactive "*r")
+ (mime-edit-enclose-region-internal 'kazu-signed beg end)
+ )
+
+(defun mime-edit-enclose-kazu-encrypted-region (beg end)
+ (interactive "*r")
+ (mime-edit-enclose-region-internal 'kazu-encrypted beg end)
+ )
+
+(defun mime-edit-enclose-smime-signed-region (beg end)
+ (interactive "*r")
+ (mime-edit-enclose-region-internal 'smime-signed beg end)
+ )
+
+(defun mime-edit-enclose-smime-encrypted-region (beg end)
+ (interactive "*r")
+ (mime-edit-enclose-region-internal 'smime-encrypted beg end)
+ )
(defun mime-edit-insert-key (&optional arg)
"Insert a pgp public key."
(interactive "P")
(mime-edit-insert-tag "application" "pgp-keys")
(mime-edit-define-encoding "7bit")
- (funcall (pgp-function 'insert-key))
- )
+ (pgg-insert-key)
+ (if (and (not (eobp))
+ (not (looking-at mime-edit-single-part-tag-regexp)))
+ (insert (mime-make-text-tag) "\n")))
;;; @ flag setting
(defun mime-edit-set-split (arg)
(interactive
(list
- (y-or-n-p "Do you want to enable split?")
+ (y-or-n-p "Do you want to enable split? ")
))
(setq mime-edit-split-message arg)
(if arg
(setq mime-transfer-level 8)
(setq mime-transfer-level 7)
))
- (setq mime-edit-charset-default-encoding-alist
- (mime-make-charset-default-encoding-alist mime-transfer-level))
(message (format "Current transfer-level is %d bit"
mime-transfer-level))
(setq mime-transfer-level-string
;;; @ pgp
;;;
+(defvar mime-edit-pgp-processing nil)
+(make-variable-buffer-local 'mime-edit-pgp-processing)
+
(defun mime-edit-set-sign (arg)
(interactive
(list
- (y-or-n-p "Do you want to sign?")
+ (y-or-n-p "Do you want to sign? ")
))
(if arg
- (if mime-edit-signing-type
- (progn
- (setq mime-edit-pgp-processing 'sign)
- (message "This message will be signed.")
- )
- (message "Please specify signing type.")
+ (progn
+ (or (memq 'sign mime-edit-pgp-processing)
+ (setq mime-edit-pgp-processing
+ (nconc mime-edit-pgp-processing
+ (copy-sequence '(sign)))))
+ (message "This message will be signed.")
)
- (if (eq mime-edit-pgp-processing 'sign)
- (setq mime-edit-pgp-processing nil)
- )
+ (setq mime-edit-pgp-processing
+ (delq 'sign mime-edit-pgp-processing))
(message "This message will not be signed.")
))
(defun mime-edit-set-encrypt (arg)
(interactive
(list
- (y-or-n-p "Do you want to encrypt?")
+ (y-or-n-p "Do you want to encrypt? ")
))
(if arg
- (if mime-edit-encrypting-type
- (progn
- (setq mime-edit-pgp-processing 'encrypt)
- (message "This message will be encrypt.")
- )
- (message "Please specify encrypting type.")
+ (progn
+ (or (memq 'encrypt mime-edit-pgp-processing)
+ (setq mime-edit-pgp-processing
+ (nconc mime-edit-pgp-processing
+ (copy-sequence '(encrypt)))))
+ (message "This message will be encrypted.")
)
- (if (eq mime-edit-pgp-processing 'encrypt)
- (setq mime-edit-pgp-processing nil)
- )
- (message "This message will not be encrypt.")
+ (setq mime-edit-pgp-processing
+ (delq 'encrypt mime-edit-pgp-processing))
+ (message "This message will not be encrypted.")
))
-(defvar mime-edit-pgp-processing nil)
-(make-variable-buffer-local 'mime-edit-pgp-processing)
-
(defun mime-edit-pgp-enclose-buffer ()
(let ((beg (save-excursion
(goto-char (point-min))
(if (search-forward (concat "\n" mail-header-separator "\n"))
(match-end 0)
)))
- (end (point-max))
)
- (if beg
- (cond ((eq mime-edit-pgp-processing 'sign)
- (mime-edit-enclose-signed-region beg end)
- )
- ((eq mime-edit-pgp-processing 'encrypt)
- (mime-edit-enclose-encrypted-region beg end)
- ))
+ (when beg
+ (if (memq 'sign mime-edit-pgp-processing)
+ (mime-edit-enclose-pgp-signed-region beg (point-max)))
+ (if (memq 'encrypt mime-edit-pgp-processing)
+ (mime-edit-enclose-pgp-encrypted-region beg (point-max)))
)))
-
;;; @ split
;;;
-(defun mime-edit-insert-partial-header
- (fields subject id number total separator)
+(defun mime-edit-insert-partial-header (fields subject
+ id number total separator)
(insert fields)
(insert (format "Subject: %s (%d/%d)\n" subject number total))
- (insert (format "Mime-Version: 1.0 (split by %s)\n"
- mime-edit-version-name))
+ (insert mime-edit-mime-version-field-for-message/partial)
(insert (format "\
Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
id number total separator))
(or (cdr (assq major-mode mime-edit-message-max-lines-alist))
mime-edit-message-default-max-lines))
)
- (let* ((mime-edit-draft-file-name
- (or (buffer-file-name)
- (make-temp-name
- (expand-file-name "mime-draft" mime-temp-directory))))
- (separator mail-header-separator)
- (id (concat "\""
- (replace-space-with-underline (current-time-string))
- "@" (system-name) "\"")))
+ (let ((separator mail-header-separator)
+ (id (concat "\""
+ (replace-space-with-underline (current-time-string))
+ "@" (system-name) "\"")))
(run-hooks 'mime-edit-before-split-hook)
(let ((the-buf (current-buffer))
(copy-buf (get-buffer-create " *Original Message*"))
(message (format "Sending %d/%d..."
mime-edit-partial-number total))
(call-interactively command)
- (message (format "Sending %d/%d... done"
+ (message (format "Sending %d/%d...done"
mime-edit-partial-number total))
)
(setq mime-edit-partial-number
(save-excursion
(message (format "Sending %d/%d..."
mime-edit-partial-number total))
- (message (format "Sending %d/%d... done"
+ (message (format "Sending %d/%d...done"
mime-edit-partial-number total))
)
)))
;;;
(defvar mime-edit-buffer nil) ; buffer local variable
+(defvar mime-edit-temp-message-buffer nil) ; buffer local variable
(defun mime-edit-preview-message ()
- "preview editing MIME message. [mime-edit.el]"
+ "preview editing MIME message."
(interactive)
(let* ((str (buffer-string))
(separator mail-header-separator)
(buf-name (buffer-name))
(temp-buf-name (concat "*temp-article:" buf-name "*"))
(buf (get-buffer temp-buf-name))
+ (pgp-processing mime-edit-pgp-processing)
)
(if buf
(progn
(setq mail-header-separator separator)
(make-local-variable 'mime-edit-buffer)
(setq mime-edit-buffer the-buf)
-
+ (setq mime-edit-pgp-processing pgp-processing)
+
(run-hooks 'mime-edit-translate-hook)
(mime-edit-translate-buffer)
(goto-char (point-min))
(concat "^" (regexp-quote separator) "$"))
(replace-match "")
)
- (mime-view-mode)
- ))
+ (mime-view-buffer)
+ (make-local-variable 'mime-edit-temp-message-buffer)
+ (setq mime-edit-temp-message-buffer buf)))
(defun mime-edit-quitting-method ()
- (let ((temp mime::preview/article-buffer)
- buf)
- (mime-view-kill-buffer)
+ "Quitting method for mime-view."
+ (let* ((temp mime-edit-temp-message-buffer)
+ buf)
+ (mime-preview-kill-buffer)
(set-buffer temp)
(setq buf mime-edit-buffer)
(kill-buffer temp)
- (switch-to-buffer buf)
- ))
+ (switch-to-buffer buf)))
-(set-alist 'mime-view-quitting-method-alist
+(set-alist 'mime-preview-quitting-method-alist
'mime-temp-message-mode
- (function mime-edit-quitting-method)
- )
+ #'mime-edit-quitting-method)
;;; @ edit again
(defvar mime-edit-again-ignored-field-regexp
(concat "^\\(" "Content-.*\\|Mime-Version"
- (if mime-edit-insert-x-emacs-field "\\|X-Emacs")
+ (if mime-edit-insert-user-agent-field "\\|User-Agent")
"\\):")
"Regexp for deleted header fields when `mime-edit-again' is called.")
-(defun mime-edit-decode-buffer (not-decode-text)
- (save-excursion
- (goto-char (point-min))
- (let ((ctl (mime/Content-Type)))
- (if ctl
- (let ((ctype (car ctl))
- (params (cdr ctl))
- type stype)
- (if (string-match "/" ctype)
- (progn
- (setq type (substring ctype 0 (match-beginning 0)))
- (setq stype (substring ctype (match-end 0)))
- )
- (setq type ctype)
- )
- (cond
- ((string= ctype "application/pgp-signature")
- (delete-region (point-min)(point-max))
- )
- ((string= type "multipart")
- (let* ((boundary (cdr (assoc "boundary" params)))
- (boundary-pat
- (concat "\n--" (regexp-quote boundary) "[ \t]*\n"))
- )
- (re-search-forward boundary-pat nil t)
- (let ((bb (match-beginning 0)) eb tag)
- (setq tag (format "\n--<<%s>>-{\n" stype))
- (goto-char bb)
- (insert tag)
- (setq bb (+ bb (length tag)))
- (re-search-forward
- (concat "\n--" (regexp-quote boundary) "--[ \t]*\n")
- nil t)
- (setq eb (match-beginning 0))
- (replace-match (format "--}-<<%s>>\n" stype))
- (save-restriction
- (narrow-to-region bb eb)
- (goto-char (point-min))
- (while (re-search-forward boundary-pat nil t)
- (let ((beg (match-beginning 0))
- end)
- (delete-region beg (match-end 0))
- (save-excursion
- (if (re-search-forward boundary-pat nil t)
- (setq end (match-beginning 0))
- (setq end (point-max))
- )
- (save-restriction
- (narrow-to-region beg end)
- (mime-edit-decode-buffer not-decode-text)
- (goto-char (point-max))
- ))))
- ))
- (goto-char (point-min))
- (or (= (point-min) 1)
- (delete-region (point-min)
+(defsubst eliminate-top-spaces (string)
+ "Eliminate top sequence of space or tab in STRING."
+ (if (string-match "^[ \t]+" string)
+ (substring string (match-end 0))
+ string))
+
+(defun mime-edit-decode-multipart-in-buffer (content-type not-decode-text)
+ (let* ((subtype
+ (or
+ (cdr (assoc (mime-content-type-parameter content-type "protocol")
+ '(("application/pgp-encrypted" . pgp-encrypted)
+ ("application/pgp-signature" . pgp-signed))))
+ (mime-content-type-subtype content-type)))
+ (boundary (mime-content-type-parameter content-type "boundary"))
+ (boundary-pat (concat "\n--" (regexp-quote boundary) "[ \t]*\n")))
+ (re-search-forward boundary-pat nil t)
+ (let ((bb (match-beginning 0)) eb tag)
+ (setq tag (format "\n--<<%s>>-{\n" subtype))
+ (goto-char bb)
+ (insert tag)
+ (setq bb (+ bb (length tag)))
+ (re-search-forward
+ (concat "\n--" (regexp-quote boundary) "--[ \t]*\n")
+ nil t)
+ (setq eb (match-beginning 0))
+ (replace-match (format "--}-<<%s>>\n" subtype))
+ (save-restriction
+ (narrow-to-region bb eb)
+ (goto-char (point-min))
+ (while (re-search-forward boundary-pat nil t)
+ (let ((beg (match-beginning 0))
+ end)
+ (delete-region beg (match-end 0))
+ (save-excursion
+ (if (re-search-forward boundary-pat nil t)
+ (setq end (match-beginning 0))
+ (setq end (point-max))
+ )
+ (save-restriction
+ (narrow-to-region beg end)
+ (cond
+ ((eq subtype 'pgp-encrypted)
+ (when (and
+ (progn
+ (goto-char (point-min))
+ (re-search-forward "^-+BEGIN PGP MESSAGE-+$"
+ nil t))
+ (prog1
+ (save-window-excursion
+ (pgg-decrypt-region (match-beginning 0)
+ (point-max)))
+ (delete-region (point-min)(point-max))))
+ (insert-buffer-substring pgg-output-buffer)
+ (mime-edit-decode-message-in-buffer
+ nil not-decode-text)
+ (delete-region (goto-char (point-min))
(if (search-forward "\n\n" nil t)
(match-end 0)
- (point-min)
- )))
- ))
- (t
- (let* (charset
- (pstr
- (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
- (if (re-search-forward
- "Content-Transfer-Encoding:" nil t)
- (let ((beg (match-beginning 0))
- (hbeg (match-end 0))
- (end (std11-field-end)))
- (setq encoding
- (eliminate-top-spaces
- (std11-unfold-string
- (buffer-substring hbeg end))))
- (if (or charset (string-equal type "text"))
- (progn
- (delete-region beg (1+ end))
- (goto-char (point-min))
- (if (search-forward "\n\n" nil t)
- (progn
- (mime-decode-region
- (match-end 0)(point-max) encoding)
- (setq encoded t
- encoding nil)
- )))))))
- (if (or encoded (not not-decode-text))
- (decode-mime-charset-region
- (point-min)(point-max)
- (or charset default-mime-charset))
- )
- (let ((he
- (if (re-search-forward "^$" nil t)
+ (point-min)))
+ (goto-char (point-max))
+ ))
+ (t
+ (mime-edit-decode-message-in-buffer
+ (if (eq subtype 'digest)
+ (eval-when-compile
+ (make-mime-content-type 'message 'rfc822))
+ )
+ not-decode-text)
+ (goto-char (point-max))
+ ))
+ ))))
+ ))
+ (goto-char (point-min))
+ (or (= (point-min) 1)
+ (delete-region (point-min)
+ (if (search-forward "\n\n" nil t)
(match-end 0)
(point-min)
)))
- (if (= (point-min) 1)
+ ))
+
+(defun mime-edit-decode-single-part-in-buffer
+ (content-type not-decode-text &optional content-disposition)
+ (let* ((type (mime-content-type-primary-type content-type))
+ (subtype (mime-content-type-subtype content-type))
+ (ctype (format "%s/%s" type subtype))
+ charset
+ (pstr (let ((bytes (+ 14 (length ctype))))
+ (mapconcat (function
+ (lambda (attr)
+ (if (string= (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)
+ )
+ ))))
+ (mime-content-type-parameters content-type) "")))
+ encoding
+ encoded
+ (limit (save-excursion
+ (if (search-forward "\n\n" nil t)
+ (1- (point)))))
+ (disposition-type
+ (mime-content-disposition-type content-disposition))
+ (disposition-str
+ (if disposition-type
+ (let ((bytes (+ 21 (length (format "%s" disposition-type)))))
+ (mapconcat (function
+ (lambda (attr)
+ (let* ((str (concat
+ (car attr)
+ "="
+ (if (string-equal "filename"
+ (car attr))
+ (std11-wrap-as-quoted-string
+ (cdr attr))
+ (cdr attr))))
+ (bs (length str)))
+ (setq bytes (+ bytes bs 2))
+ (if (< bytes 76)
+ (concat "; " str)
+ (setq bytes (+ bs 1))
+ (concat ";\n " str)
+ )
+ )))
+ (mime-content-disposition-parameters
+ content-disposition)
+ ""))))
+ )
+ (if disposition-type
+ (setq pstr (format "%s\nContent-Disposition: %s%s"
+ pstr disposition-type disposition-str))
+ )
+ (save-excursion
+ (if (re-search-forward
+ "^Content-Transfer-Encoding:" limit t)
+ (let ((beg (match-beginning 0))
+ (hbeg (match-end 0))
+ (end (std11-field-end limit)))
+ (setq encoding
+ (downcase
+ (eliminate-top-spaces
+ (std11-unfold-string
+ (buffer-substring hbeg end)))))
+ (if (or charset (eq type 'text))
+ (progn
+ (delete-region beg (1+ end))
+ (goto-char (point-min))
+ (if (search-forward "\n\n" nil t)
(progn
- (goto-char he)
- (insert
- (concat "\n"
- (mime-create-tag
- (concat type "/" stype pstr) encoding)))
- )
- (delete-region (point-min) he)
- (insert
+ (mime-decode-region
+ (match-end 0)(point-max) encoding)
+ (setq encoded t
+ encoding nil)
+ )))))))
+ (if (and (eq type 'text)
+ (or encoded (not not-decode-text)))
+ (progn
+ (save-excursion
+ (goto-char (point-min))
+ (while (re-search-forward "\r\n" nil t)
+ (replace-match "\n")
+ ))
+ (decode-mime-charset-region (point-min)(point-max)
+ (or charset default-mime-charset))
+ ))
+ (let ((he (if (re-search-forward "^$" nil t)
+ (match-end 0)
+ (point-min)
+ )))
+ (if (and (eq type 'text)
+ (eq subtype 'x-rot13-47-48))
+ (mule-caesar-region he (point-max))
+ )
+ (if (= (point-min) 1)
+ (progn
+ (goto-char he)
+ (insert
+ (concat "\n"
(mime-create-tag
- (concat type "/" stype pstr) encoding))
- ))
- ))))
+ (format "%s/%s%s" type subtype pstr)
+ encoding)))
+ )
+ (delete-region (point-min) he)
+ (insert
+ (mime-create-tag (format "%s/%s%s" type subtype pstr)
+ encoding))
+ ))
+ ))
+
+;;;###autoload
+(defun mime-edit-decode-message-in-buffer (&optional default-content-type
+ not-decode-text)
+ (save-excursion
+ (goto-char (point-min))
+ (let ((ctl (or (mime-read-Content-Type)
+ default-content-type)))
+ (if ctl
+ (let ((type (mime-content-type-primary-type ctl)))
+ (cond
+ ((and (eq type 'application)
+ (eq (mime-content-type-subtype ctl) 'pgp-signature))
+ (delete-region (point-min)(point-max))
+ )
+ ((eq type 'multipart)
+ (mime-edit-decode-multipart-in-buffer ctl not-decode-text)
+ )
+ (t
+ (mime-edit-decode-single-part-in-buffer
+ ctl not-decode-text (mime-read-Content-Disposition))
+ )))
(or not-decode-text
(decode-mime-charset-region (point-min) (point-max)
- default-mime-charset)
- )
- ))))
+ default-mime-charset))
+ )
+ (if (= (point-min) 1)
+ (progn
+ (save-restriction
+ (std11-narrow-to-header)
+ (goto-char (point-min))
+ (while (re-search-forward
+ mime-edit-again-ignored-field-regexp nil t)
+ (delete-region (match-beginning 0) (1+ (std11-field-end)))
+ ))
+ (mime-decode-header-in-buffer (not not-decode-text))
+ ))
+ )))
+;;;###autoload
(defun mime-edit-again (&optional not-decode-text no-separator not-turn-on)
"Convert current buffer to MIME-Edit buffer and turn on MIME-Edit mode.
Content-Type and Content-Transfer-Encoding header fields will be
nil t)
(replace-match "\n\n")
)
- (mime-edit-decode-buffer not-decode-text)
+ (mime-edit-decode-message-in-buffer nil not-decode-text)
(goto-char (point-min))
- (save-restriction
- (std11-narrow-to-header)
- (goto-char (point-min))
- (while (re-search-forward mime-edit-again-ignored-field-regexp nil t)
- (delete-region (match-beginning 0) (1+ (std11-field-end)))
- ))
(or no-separator
(and (re-search-forward "^$")
(replace-match mail-header-separator)