;;; mml.el --- A package for parsing and validating MML documents
;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-;; 2005 Free Software Foundation, Inc.
+;; 2005, 2006 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; This file is part of GNU Emacs.
(autoload 'gnus-make-local-hook "gnus-util")
(autoload 'message-fetch-field "message")
(autoload 'message-mark-active-p "message")
+ (autoload 'message-info "message")
(autoload 'fill-flowed-encode "flow-fill")
- (autoload 'message-posting-charset "message"))
-
-(eval-when-compile
+ (autoload 'message-posting-charset "message")
(autoload 'dnd-get-local-file-name "dnd"))
+(defvar gnus-article-mime-handles)
+(defvar gnus-mouse-2)
+(defvar gnus-newsrc-hashtb)
+(defvar message-default-charset)
+(defvar message-deletable-headers)
+(defvar message-options)
+(defvar message-posting-charset)
+(defvar message-required-mail-headers)
+(defvar message-required-news-headers)
+(defvar dnd-protocol-alist)
+
(defcustom mml-content-type-parameters
'(name access-type expiration size permission format)
"*A list of acceptable parameters in MML tag.
(mm-find-buffer-file-coding-system
filename)))))
(t
- (insert (cdr (assq 'contents cont)))))
+ (let ((contents (cdr (assq 'contents cont))))
+ (if (if (featurep 'xemacs)
+ (string-match "[^\000-\377]" contents)
+ (mm-multibyte-string-p contents))
+ (progn
+ (mm-enable-multibyte)
+ (insert contents)
+ (setq charset (mm-encode-body charset)))
+ (insert contents)))))
(setq encoding (mm-encode-buffer type)
coded (mm-string-as-multibyte (buffer-string))))
(mml-insert-mime-headers cont type charset encoding nil)
;; Skip `multipart' and attributes.
(when (and (consp part) (consp (cdr part)))
(insert "\n--" mml-boundary "\n")
- (mml-generate-mime-1 part))))
+ (mml-generate-mime-1 part)
+ (goto-char (point-max)))))
(insert "\n--" mml-boundary "--\n")))))
(t
(error "Invalid element: %S" cont)))
"Can't encode a part with several charsets"))
(insert "Content-Type: " type)
(when charset
- (insert "; " (mail-header-encode-parameter
- "charset" (symbol-name charset))))
+ (mml-insert-parameter
+ (mail-header-encode-parameter "charset" (symbol-name charset))))
(when flowed
- (insert "; format=flowed"))
+ (mml-insert-parameter "format=flowed"))
(when parameters
(mml-insert-parameter-string
cont mml-content-type-parameters))
(unless (eq encoding '7bit)
(insert (format "Content-Transfer-Encoding: %s\n" encoding)))
(when (setq description (cdr (assq 'description cont)))
- (insert "Content-Description: "
- (mail-encode-encoded-word-string description) "\n"))))
+ (insert "Content-Description: ")
+ (setq description (prog1
+ (point)
+ (insert description "\n")))
+ (mail-encode-encoded-word-region description (point)))))
(defun mml-parameter-string (cont types)
(let ((string "")
(unless (setq textp (equal (mm-handle-media-supertype handle) "text"))
(save-excursion
(set-buffer (setq buffer (mml-generate-new-buffer " *mml*")))
- (mm-insert-part handle)
+ (mm-insert-part handle 'no-cache)
(if (setq mmlp (equal (mm-handle-media-type handle)
"message/rfc822"))
(mime-to-mml)))))
(defun mml-insert-parameter (&rest parameters)
"Insert PARAMETERS in a nice way."
- (dolist (param parameters)
- (insert ";")
- (let ((point (point)))
+ (let (start end)
+ (dolist (param parameters)
+ (insert ";")
+ (setq start (point))
(insert " " param)
- (when (> (current-column) 71)
- (goto-char point)
- (insert "\n")
- (end-of-line)))))
+ (setq end (point))
+ (goto-char start)
+ (end-of-line)
+ (if (> (current-column) 76)
+ (progn
+ (goto-char start)
+ (insert "\n")
+ (goto-char (1+ end)))
+ (goto-char end)))))
;;;
;;; Mode for inserting and editing MML forms
(encryptpart (make-sparse-keymap))
(map (make-sparse-keymap))
(main (make-sparse-keymap)))
+ (define-key map "\C-s" 'mml-secure-message-sign)
+ (define-key map "\C-c" 'mml-secure-message-encrypt)
+ (define-key map "\C-e" 'mml-secure-message-sign-encrypt)
+ (define-key map "\C-p\C-s" 'mml-secure-sign)
+ (define-key map "\C-p\C-c" 'mml-secure-encrypt)
(define-key sign "p" 'mml-secure-message-sign-pgpmime)
(define-key sign "o" 'mml-secure-message-sign-pgp)
(define-key sign "s" 'mml-secure-message-sign-smime)
["Attach File..." mml-attach-file
,@(if (featurep 'xemacs) '(t)
'(:help "Attach a file at point"))]
- ["Attach Buffer..." mml-attach-buffer t]
- ["Attach External..." mml-attach-external t]
- ["Insert Part..." mml-insert-part t]
- ["Insert Multipart..." mml-insert-multipart t]
- ["PGP/MIME Sign" mml-secure-message-sign-pgpmime t]
- ["PGP/MIME Encrypt" mml-secure-message-encrypt-pgpmime t]
- ["PGP Sign" mml-secure-message-sign-pgp t]
- ["PGP Encrypt" mml-secure-message-encrypt-pgp t]
- ["S/MIME Sign" mml-secure-message-sign-smime t]
- ["S/MIME Encrypt" mml-secure-message-encrypt-smime t]
- ("Secure MIME part"
- ["PGP/MIME Sign Part" mml-secure-sign-pgpmime t]
- ["PGP/MIME Encrypt Part" mml-secure-encrypt-pgpmime t]
- ["PGP Sign Part" mml-secure-sign-pgp t]
- ["PGP Encrypt Part" mml-secure-encrypt-pgp t]
- ["S/MIME Sign Part" mml-secure-sign-smime t]
- ["S/MIME Encrypt Part" mml-secure-encrypt-smime t])
- ["Encrypt/Sign off" mml-unsecure-message t]
+ ["Attach Buffer..." mml-attach-buffer
+ ,@(if (featurep 'xemacs) '(t)
+ '(:help "Attach a buffer to the outgoing MIME message"))]
+ ["Attach External..." mml-attach-external
+ ,@(if (featurep 'xemacs) '(t)
+ '(:help "Attach reference to file"))]
+ ;;
+ ("Change Security Method"
+ ["PGP/MIME"
+ (lambda () (interactive) (setq mml-secure-method "pgpmime"))
+ ,@(if (featurep 'xemacs) nil
+ '(:help "Set Security Method to PGP/MIME"))
+ :style radio
+ :selected (equal mml-secure-method "pgpmime") ]
+ ["S/MIME"
+ (lambda () (interactive) (setq mml-secure-method "smime"))
+ ,@(if (featurep 'xemacs) nil
+ '(:help "Set Security Method to S/MIME"))
+ :style radio
+ :selected (equal mml-secure-method "smime") ]
+ ["Inline PGP"
+ (lambda () (interactive) (setq mml-secure-method "pgp"))
+ ,@(if (featurep 'xemacs) nil
+ '(:help "Set Security Method to inline PGP"))
+ :style radio
+ :selected (equal mml-secure-method "pgp") ] )
+ ;;
+ ["Sign Message" mml-secure-message-sign t]
+ ["Encrypt Message" mml-secure-message-encrypt t]
+ ["Sign and Encrypt Message" mml-secure-message-sign-encrypt t]
+ ["Encrypt/Sign off" mml-unsecure-message
+ ,@(if (featurep 'xemacs) '(t)
+ '(:help "Don't Encrypt/Sign Message"))]
+ ;; Maybe we could remove these, because people who write MML most probably
+ ;; don't use the menu:
+ ["Insert Part..." mml-insert-part
+ :active (message-in-body-p)]
+ ["Insert Multipart..." mml-insert-multipart
+ :active (message-in-body-p)]
+ ;;
+ ;; Do we have separate encrypt and encrypt/sign commands for parts?
+ ["Sign Part" mml-secure-sign t]
+ ["Encrypt Part" mml-secure-encrypt t]
;;["Narrow" mml-narrow-to-part t]
- ["Quote MML" mml-quote-region
+ ["Quote MML in region" mml-quote-region
:active (message-mark-active-p)
,@(if (featurep 'xemacs) nil
'(:help "Quote MML tags in region"))]
["Validate MML" mml-validate t]
- ["Preview" mml-preview t]))
+ ["Preview" mml-preview t]
+ "----"
+ ["Emacs MIME manual" (lambda () (interactive) (message-info 4))
+ ,@(if (featurep 'xemacs) '(t)
+ '(:help "Display the Emacs MIME manual"))]
+ ["PGG manual" (lambda () (interactive) (message-info 16))
+ ,@(if (featurep 'xemacs) '(t)
+ '(:help "Display the PGG manual"))]))
(defvar mml-mode nil
"Minor mode for editing MML.")
;;; inserting stuff to the buffer.
;;;
+(defcustom mml-default-directory mm-default-directory
+ "The default directory where mml will find files.
+If not set, `default-directory' will be used."
+ :type '(choice directory (const :tag "Default" nil))
+ :version "23.0" ;; No Gnus
+ :group 'message)
+
(defun mml-minibuffer-read-file (prompt)
(let* ((completion-ignored-extensions nil)
- (file (read-file-name prompt nil nil t)))
+ (file (read-file-name prompt
+ (or mml-default-directory default-directory)
+ nil t)))
;; Prevent some common errors. This is inspired by similar code in
;; VM.
(when (file-directory-p file)
as in other buffers."
:type '(choice (repeat (cons (regexp) (function)))
(const :tag "Behave as in other buffers" nil))
- :version "23.0" ;; No Gnus
+ :version "22.1" ;; Gnus 5.10.9
:group 'message)
(defcustom mml-dnd-attach-options nil
(const type)
(const description)
(const disposition))))
- :version "23.0" ;; No Gnus
+ :version "22.1" ;; Gnus 5.10.9
:group 'message)
(defun mml-attach-file (file &optional type description disposition)
The file is not inserted or encoded until you send the message with
`\\[message-send-and-exit]' or `\\[message-send]'.
-FILE is the name of the file to attach. TYPE is its content-type, a
-string of the form \"type/subtype\". DESCRIPTION is a one-line
-description of the attachment."
+FILE is the name of the file to attach. TYPE is its
+content-type, a string of the form \"type/subtype\". DESCRIPTION
+is a one-line description of the attachment. The DISPOSITION
+specifies how the attachment is intended to be displayed. It can
+be either \"inline\" (displayed automatically within the message
+body) or \"attachment\" (separate from the body)."
(interactive
(let* ((file (mml-minibuffer-read-file "Attach file: "))
(type (mml-minibuffer-read-type file))
(description (mml-minibuffer-read-description))
(disposition (mml-minibuffer-read-disposition type)))
(list file type description disposition)))
- (mml-insert-empty-tag 'part
- 'type type
- 'filename file
- 'disposition (or disposition "attachment")
- 'description description))
+ (save-excursion
+ (unless (message-in-body-p) (goto-char (point-max)))
+ (mml-insert-empty-tag 'part
+ 'type type
+ 'filename file
+ 'disposition (or disposition "attachment")
+ 'description description)))
(defun mml-dnd-attach-file (uri action)
"Attach a drag and drop file.
(type (mml-minibuffer-read-type buffer "text/plain"))
(description (mml-minibuffer-read-description)))
(list buffer type description)))
- (mml-insert-empty-tag 'part 'type type 'buffer buffer
- 'disposition "attachment" 'description description))
+ (save-excursion
+ (unless (message-in-body-p) (goto-char (point-max)))
+ (mml-insert-empty-tag 'part 'type type 'buffer buffer
+ 'disposition "attachment"
+ 'description description)))
(defun mml-attach-external (file &optional type description)
"Attach an external file into the buffer.
(type (mml-minibuffer-read-type file))
(description (mml-minibuffer-read-description)))
(list file type description)))
- (mml-insert-empty-tag 'external 'type type 'name file
- 'disposition "attachment" 'description description))
+ (save-excursion
+ (unless (message-in-body-p) (goto-char (point-max)))
+ (mml-insert-empty-tag 'external 'type type 'name file
+ 'disposition "attachment" 'description description)))
(defun mml-insert-multipart (&optional type)
(interactive (list (completing-read "Multipart type (default mixed): "
(defun mml-preview (&optional raw)
"Display current buffer with Gnus, in a new buffer.
-If RAW, don't highlight the article."
+If RAW, display a raw encoded MIME message.
+
+The window layout for the preview buffer is controled by the variables
+`special-display-buffer-names', `special-display-regexps', or
+`gnus-buffer-configuration' (the first match made will be used),
+or the `pop-to-buffer' function."
(interactive "P")
(setq mml-preview-buffer (generate-new-buffer
(concat (if raw "*Raw MIME preview of "
(lambda (event)
(interactive "@e")
(widget-button-press (widget-event-point event) event)))
+ ;; FIXME: Buffer is in article mode, but most tool bar commands won't
+ ;; work. Maybe only keep the following icons: search, print, quit
(goto-char (point-min))))
- (if (and (boundp 'gnus-buffer-configuration)
+ (if (and (not (mm-special-display-p (buffer-name mml-preview-buffer)))
+ (boundp 'gnus-buffer-configuration)
(assq 'mml-preview gnus-buffer-configuration))
(let ((gnus-message-buffer (current-buffer)))
(gnus-configure-windows 'mml-preview))