(nnimap-verify-uidvalidity): Fixed bug where uidvalidity
[gnus] / lisp / mml.el
index 4fdef84..87fcdf5 100644 (file)
@@ -1,25 +1,23 @@
 ;;; mml.el --- A package for parsing and validating MML documents
 
-;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-;;   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+;;   2007, 2008, 2009, 2010  Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
 (require 'mml-sec)
 (eval-when-compile (require 'cl))
 
-(eval-and-compile
-  (autoload 'message-make-message-id "message")
-  (autoload 'gnus-setup-posting-charset "gnus-msg")
-  (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")
-  (autoload 'dnd-get-local-file-name "dnd"))
+(autoload 'message-make-message-id "message")
+(autoload 'gnus-setup-posting-charset "gnus-msg")
+(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")
+(autoload 'dnd-get-local-file-name "dnd")
 
 (autoload 'message-options-set    "message")
 (autoload 'message-narrow-to-head "message")
@@ -395,8 +392,8 @@ A message part needs to be split into %d charset parts.  Really send? "
       (skip-chars-forward "= \t\n")
       (setq val (buffer-substring-no-properties
                 (point) (progn (forward-sexp 1) (point))))
-      (when (string-match "^\"\\(.*\\)\"$" val)
-       (setq val (match-string 1 val)))
+      (when (string-match "\\`\"" val)
+       (setq val (read val))) ;; inverse of prin1 in mml-insert-tag
       (push (cons (intern elem) val) contents)
       (skip-chars-forward " \t\n"))
     (goto-char (match-end 0))
@@ -485,7 +482,12 @@ If MML is non-nil, return the buffer up till the correspondent mml tag."
                 (setq charset nil
                       coding nil))
                (charset
-                (setq charset (intern (downcase charset)))))
+                ;; The value of `charset' might be a bogus alias that
+                ;; `mm-charset-synonym-alist' provides, like `utf8',
+                ;; so we prefer the MIME charset that Emacs knows for
+                ;; the coding system `coding'.
+                (setq charset (or (mm-coding-system-to-mime-charset coding)
+                                  (intern (downcase charset))))))
          (if (and (not raw)
                   (member (car (split-string type "/")) '("text" "message")))
              (progn
@@ -583,7 +585,9 @@ If MML is non-nil, return the buffer up till the correspondent mml tag."
                        (unless raw
                          (setq charset (mm-encode-body charset))))
                    (insert contents)))))
-             (setq encoding (mm-encode-buffer type)
+             (if (setq encoding (cdr (assq 'encoding cont)))
+                 (setq encoding (intern (downcase encoding))))
+             (setq encoding (mm-encode-buffer type encoding)
                    coded (mm-string-as-multibyte (buffer-string))))
            (mml-insert-mime-headers cont type charset encoding nil)
            (insert "\n" coded))))
@@ -896,10 +900,17 @@ If HANDLES is non-nil, use it instead reparsing the buffer."
       (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 'no-cache)
-         (if (setq mmlp (equal (mm-handle-media-type handle)
-                               "message/rfc822"))
-             (mime-to-mml)))))
+         (if (eq (mail-content-type-get (mm-handle-type handle) 'charset)
+                 'gnus-decoded)
+             ;; A part that mm-uu dissected from a non-MIME message
+             ;; because of `gnus-article-emulate-mime'.
+             (progn
+               (mm-enable-multibyte)
+               (insert-buffer-substring (mm-handle-buffer handle)))
+           (mm-insert-part handle 'no-cache)
+           (if (setq mmlp (equal (mm-handle-media-type handle)
+                                 "message/rfc822"))
+               (mime-to-mml))))))
     (if mmlp
        (mml-insert-mml-markup handle nil t t)
       (unless (and no-markup
@@ -1034,13 +1045,20 @@ If HANDLES is non-nil, use it instead reparsing the buffer."
     ["Externalize Attachments"
      (lambda ()
        (interactive)
-       (setq gnus-gcc-externalize-attachments
-            (not gnus-gcc-externalize-attachments))
-       (message "gnus-gcc-externalize-attachments is `%s'."
-               gnus-gcc-externalize-attachments))
-     :visible (and (boundp 'gnus-gcc-externalize-attachments)
-                  (memq gnus-gcc-externalize-attachments
-                        '(all t nil)))
+       (if (not (and (boundp 'gnus-gcc-externalize-attachments)
+                    (memq gnus-gcc-externalize-attachments
+                          '(all t nil))))
+          ;; Stupid workaround for XEmacs not honoring :visible.
+          (message "Can't handle this value of `gnus-gcc-externalize-attachments'")
+        (setq gnus-gcc-externalize-attachments
+              (not gnus-gcc-externalize-attachments))
+        (message "gnus-gcc-externalize-attachments is `%s'."
+                 gnus-gcc-externalize-attachments)))
+     ;; XEmacs barfs on :visible.
+     ,@(if (featurep 'xemacs) nil
+        '(:visible (and (boundp 'gnus-gcc-externalize-attachments)
+                        (memq gnus-gcc-externalize-attachments
+                              '(all t nil)))))
      :style toggle
      :selected gnus-gcc-externalize-attachments
      ,@(if (featurep 'xemacs) nil
@@ -1096,11 +1114,15 @@ If HANDLES is non-nil, use it instead reparsing the buffer."
      ,@(if (featurep 'xemacs) '(t)
         '(:help "Display the Emacs MIME manual"))]
     ["PGG manual" (lambda () (interactive) (message-info mml2015-use))
-     :visible (equal mml2015-use 'pgg)
+     ;; XEmacs barfs on :visible.
+     ,@(if (featurep 'xemacs) nil
+        '(:visible (and (boundp 'mml2015-use) (equal mml2015-use 'pgg))))
      ,@(if (featurep 'xemacs) '(t)
         '(:help "Display the PGG manual"))]
-    ["EasyPG manual" (lambda () (interactive) (message-info mml2015-use))
-     :visible (equal mml2015-use 'epg)
+    ["EasyPG manual" (lambda () (interactive) (require 'mml2015) (message-info mml2015-use))
+     ;; XEmacs barfs on :visible.
+     ,@(if (featurep 'xemacs) nil
+        '(:visible (and (boundp 'mml2015-use) (equal mml2015-use 'epg))))
      ,@(if (featurep 'xemacs) '(t)
         '(:help "Display the EasyPG manual"))]))
 
@@ -1272,13 +1294,24 @@ body) or \"attachment\" (separate from the body)."
          (description (mml-minibuffer-read-description))
          (disposition (mml-minibuffer-read-disposition type nil file)))
      (list file type description disposition)))
-  (save-excursion
-    (unless (message-in-body-p) (goto-char (point-max)))
+  ;; Don't move point if this command is invoked inside the message header.
+  (let ((head (unless (message-in-body-p)
+               (prog1
+                   (point)
+                 (goto-char (point-max))))))
     (mml-insert-empty-tag 'part
                          'type type
-                         'filename file
+                         ;; icicles redefines read-file-name and returns a
+                         ;; string w/ text properties :-/
+                         'filename (mm-substring-no-properties file)
                          'disposition (or disposition "attachment")
-                         'description description)))
+                         'description description)
+    (when head
+      (unless (prog1
+                 (pos-visible-in-window-p)
+               (goto-char head))
+       (message "The file \"%s\" has been attached at the end of the message"
+                (file-name-nondirectory file))))))
 
 (defun mml-dnd-attach-file (uri action)
   "Attach a drag and drop file.
@@ -1304,19 +1337,31 @@ Ask for type, description or disposition according to
          (setq disposition (mml-minibuffer-read-disposition type nil file)))
        (mml-attach-file file type description disposition)))))
 
-(defun mml-attach-buffer (buffer &optional type description)
+(defun mml-attach-buffer (buffer &optional type description disposition)
   "Attach a buffer to the outgoing MIME message.
-See `mml-attach-file' for details of operation."
+BUFFER is the name of the buffer to attach.  See
+`mml-attach-file' for details of operation."
   (interactive
    (let* ((buffer (read-buffer "Attach buffer: "))
          (type (mml-minibuffer-read-type buffer "text/plain"))
-         (description (mml-minibuffer-read-description)))
-     (list buffer type description)))
-  (save-excursion
-    (unless (message-in-body-p) (goto-char (point-max)))
+         (description (mml-minibuffer-read-description))
+         (disposition (mml-minibuffer-read-disposition type nil)))
+     (list buffer type description disposition)))
+  ;; Don't move point if this command is invoked inside the message header.
+  (let ((head (unless (message-in-body-p)
+               (prog1
+                   (point)
+                 (goto-char (point-max))))))
     (mml-insert-empty-tag 'part 'type type 'buffer buffer
-                         'disposition "attachment"
-                         'description description)))
+                         'disposition disposition
+                         'description description)
+    (when head
+      (unless (prog1
+                 (pos-visible-in-window-p)
+               (goto-char head))
+       (message
+        "The buffer \"%s\" has been attached at the end of the message"
+        buffer)))))
 
 (defun mml-attach-external (file &optional type description)
   "Attach an external file into the buffer.
@@ -1327,26 +1372,38 @@ TYPE is the MIME type to use."
          (type (mml-minibuffer-read-type file))
          (description (mml-minibuffer-read-description)))
      (list file type description)))
-  (save-excursion
-    (unless (message-in-body-p) (goto-char (point-max)))
+  ;; Don't move point if this command is invoked inside the message header.
+  (let ((head (unless (message-in-body-p)
+               (prog1
+                   (point)
+                 (goto-char (point-max))))))
     (mml-insert-empty-tag 'external 'type type 'name file
-                         'disposition "attachment" 'description description)))
+                         'disposition "attachment" 'description description)
+    (when head
+      (unless (prog1
+                 (pos-visible-in-window-p)
+               (goto-char head))
+       (message "The file \"%s\" has been attached at the end of the message"
+                (file-name-nondirectory file))))))
 
 (defun mml-insert-multipart (&optional type)
-  (interactive (list (completing-read "Multipart type (default mixed): "
-                                     '(("mixed") ("alternative") ("digest") ("parallel")
-                                       ("signed") ("encrypted"))
-                                     nil nil "mixed")))
+  (interactive (if (message-in-body-p)
+                  (list (completing-read "Multipart type (default mixed): "
+                                         '(("mixed") ("alternative")
+                                           ("digest") ("parallel")
+                                           ("signed") ("encrypted"))
+                                         nil nil "mixed"))
+                (error "Use this command in the message body")))
   (or type
       (setq type "mixed"))
   (mml-insert-empty-tag "multipart" 'type type)
   (forward-line -1))
 
 (defun mml-insert-part (&optional type)
-  (interactive
-   (list (mml-minibuffer-read-type "")))
-  (mml-insert-tag 'part 'type type 'disposition "inline")
-  (forward-line -1))
+  (interactive (if (message-in-body-p)
+                  (list (mml-minibuffer-read-type ""))
+                (error "Use this command in the message body")))
+  (mml-insert-tag 'part 'type type 'disposition "inline"))
 
 (declare-function message-subscribed-p "message" ())
 (declare-function message-make-mail-followup-to "message"
@@ -1505,5 +1562,5 @@ or the `pop-to-buffer' function."
 
 (provide 'mml)
 
-;;; arch-tag: 583c96cf-1ffe-451b-a5e5-4733ae9ddd12
+;; arch-tag: 583c96cf-1ffe-451b-a5e5-4733ae9ddd12
 ;;; mml.el ends here