comparison lisp/mh-e/mh-mime.el @ 89966:d8411455de48

Revision: miles@gnu.org--gnu-2004/emacs--unicode--0--patch-32 Merge from emacs--cvs-trunk--0 Patches applied: * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-486 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-487 Tweak permissions * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-488 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-489 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-490 Update from CVS: man/fixit.texi (Spelling): Fix typo. * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-491 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-494 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-495 Update from CVS: Add missing lisp/mh-e files * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-496 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-499 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-500 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-513 Update from CVS
author Miles Bader <miles@gnu.org>
date Fri, 27 Aug 2004 07:00:34 +0000
parents 97905c4f1a42 25da1d331c99
children 4da4a09e8b1b
comparison
equal deleted inserted replaced
89965:5e9097d1ad99 89966:d8411455de48
32 32
33 ;;; Change Log: 33 ;;; Change Log:
34 34
35 ;;; Code: 35 ;;; Code:
36 36
37 (require 'mh-utils) 37 (eval-when-compile (require 'mh-acros))
38 (mh-require-cl) 38 (mh-require-cl)
39 (require 'mh-comp) 39 (require 'mh-comp)
40 (require 'gnus-util) 40 (require 'gnus-util)
41 (require 'mh-gnus) 41 (require 'mh-gnus)
42 42
44 (autoload 'article-emphasize "gnus-art") 44 (autoload 'article-emphasize "gnus-art")
45 (autoload 'gnus-get-buffer-create "gnus") 45 (autoload 'gnus-get-buffer-create "gnus")
46 (autoload 'gnus-eval-format "gnus-spec") 46 (autoload 'gnus-eval-format "gnus-spec")
47 (autoload 'widget-convert-button "wid-edit") 47 (autoload 'widget-convert-button "wid-edit")
48 (autoload 'message-options-set-recipient "message") 48 (autoload 'message-options-set-recipient "message")
49 (autoload 'mml-secure-message-sign-pgpmime "mml-sec") 49 (autoload 'mml-unsecure-message "mml-sec")
50 (autoload 'mml-secure-message-encrypt-pgpmime "mml-sec")
51 (autoload 'mml-minibuffer-read-file "mml") 50 (autoload 'mml-minibuffer-read-file "mml")
52 (autoload 'mml-minibuffer-read-description "mml") 51 (autoload 'mml-minibuffer-read-description "mml")
53 (autoload 'mml-insert-empty-tag "mml") 52 (autoload 'mml-insert-empty-tag "mml")
54 (autoload 'mml-to-mime "mml") 53 (autoload 'mml-to-mime "mml")
55 (autoload 'mml-attach-file "mml") 54 (autoload 'mml-attach-file "mml")
80 If any of the optional arguments are absent, they are prompted for." 79 If any of the optional arguments are absent, they are prompted for."
81 (interactive (list 80 (interactive (list
82 (read-string "Forw Content-description: ") 81 (read-string "Forw Content-description: ")
83 (mh-prompt-for-folder "Message from" mh-sent-from-folder nil) 82 (mh-prompt-for-folder "Message from" mh-sent-from-folder nil)
84 (read-string (format "Messages%s: " 83 (read-string (format "Messages%s: "
85 (if mh-sent-from-msg 84 (if (numberp mh-sent-from-msg)
86 (format " [%d]" mh-sent-from-msg) 85 (format " [%d]" mh-sent-from-msg)
87 ""))))) 86 "")))))
88 (if (equal mh-compose-insertion 'gnus) 87 (if (equal mh-compose-insertion 'gnus)
89 (mh-mml-forward-message description folder message) 88 (mh-mml-forward-message description folder message)
90 (mh-mhn-compose-forw description folder message))) 89 (mh-mhn-compose-forw description folder message)))
112 111
113 ;; Just defvar the variable to avoid compiler warning... This doesn't bind 112 ;; Just defvar the variable to avoid compiler warning... This doesn't bind
114 ;; the variable, so things should work exactly as before. 113 ;; the variable, so things should work exactly as before.
115 (defvar mh-have-file-command) 114 (defvar mh-have-file-command)
116 115
116 ;;;###mh-autoload
117 (defun mh-have-file-command () 117 (defun mh-have-file-command ()
118 "Return t if 'file' command is on the system. 118 "Return t if 'file' command is on the system.
119 'file -i' is used to get MIME type of composition insertion." 119 'file -i' is used to get MIME type of composition insertion."
120 (when (not (boundp 'mh-have-file-command)) 120 (when (not (boundp 'mh-have-file-command))
121 (load "executable" t t) ; executable-find not autoloaded in emacs20 121 (load "executable" t t) ; executable-find not autoloaded in emacs20
127 (expand-file-name "inc" mh-progs)))))) 127 (expand-file-name "inc" mh-progs))))))
128 mh-have-file-command) 128 mh-have-file-command)
129 129
130 (defvar mh-file-mime-type-substitutions 130 (defvar mh-file-mime-type-substitutions
131 '(("application/msword" "\.xls" "application/ms-excel") 131 '(("application/msword" "\.xls" "application/ms-excel")
132 ("application/msword" "\.ppt" "application/ms-powerpoint")) 132 ("application/msword" "\.ppt" "application/ms-powerpoint")
133 ("text/plain" "\.vcf" "text/x-vcard"))
133 "Substitutions to make for Content-Type returned from file command. 134 "Substitutions to make for Content-Type returned from file command.
134 The first element is the Content-Type returned by the file command. 135 The first element is the Content-Type returned by the file command.
135 The second element is a regexp matching the file name, usually the extension. 136 The second element is a regexp matching the file name, usually the extension.
136 The third element is the Content-Type to replace with.") 137 The third element is the Content-Type to replace with.")
137 138
149 (setq answer (elt (car subst) 2) 150 (setq answer (elt (car subst) 2)
150 subst nil) 151 subst nil)
151 (setq subst (cdr subst)))) 152 (setq subst (cdr subst))))
152 answer)) 153 answer))
153 154
155 ;;;###mh-autoload
154 (defun mh-file-mime-type (filename) 156 (defun mh-file-mime-type (filename)
155 "Return MIME type of FILENAME from file command. 157 "Return MIME type of FILENAME from file command.
156 Returns nil if file command not on system." 158 Returns nil if file command not on system."
157 (cond 159 (cond
158 ((not (mh-have-file-command)) 160 ((not (mh-have-file-command))
190 192
191 ("message/delivery-status") 193 ("message/delivery-status")
192 ("message/external-body") ("message/partial") ("message/rfc822") 194 ("message/external-body") ("message/partial") ("message/rfc822")
193 195
194 ("text/enriched") ("text/html") ("text/plain") ("text/rfc822-headers") 196 ("text/enriched") ("text/html") ("text/plain") ("text/rfc822-headers")
195 ("text/richtext") ("text/xml") 197 ("text/richtext") ("text/x-vcard") ("text/xml")
196 198
197 ("video/mpeg") ("video/quicktime")) 199 ("video/mpeg") ("video/quicktime"))
198 "Legal MIME content types. 200 "Legal MIME content types.
199 See documentation for \\[mh-edit-mhn].") 201 See documentation for \\[mh-edit-mhn].")
202
203 ;; RFC 2045 - Multipurpose Internet Mail Extensions (MIME) Part One:
204 ;; Format of Internet Message Bodies.
205 ;; RFC 2046 - Multipurpose Internet Mail Extensions (MIME) Part Two:
206 ;; Media Types.
207 ;; RFC 2049 - Multipurpose Internet Mail Extensions (MIME) Part Five:
208 ;; Conformance Criteria and Examples.
209 ;; RFC 2017 - Definition of the URL MIME External-Body Access-Type
210 ;; RFC 1738 - Uniform Resource Locators (URL)
211 (defvar mh-access-types
212 '(("anon-ftp") ; RFC2046 Anonymous File Transfer Protocol
213 ("file") ; RFC1738 Host-specific file names
214 ("ftp") ; RFC2046 File Transfer Protocol
215 ("gopher") ; RFC1738 The Gopher Protocol
216 ("http") ; RFC1738 Hypertext Transfer Protocol
217 ("local-file") ; RFC2046 Local file access
218 ("mail-server") ; RFC2046 mail-server Electronic mail address
219 ("mailto") ; RFC1738 Electronic mail address
220 ("news") ; RFC1738 Usenet news
221 ("nntp") ; RFC1738 Usenet news using NNTP access
222 ("propspero") ; RFC1738 Prospero Directory Service
223 ("telnet") ; RFC1738 Telnet
224 ("tftp") ; RFC2046 Trivial File Transfer Protocol
225 ("url") ; RFC2017 URL scheme MIME access-type Protocol
226 ("wais")) ; RFC1738 Wide Area Information Servers
227 "Legal MIME access-type values.")
200 228
201 ;;;###mh-autoload 229 ;;;###mh-autoload
202 (defun mh-mhn-compose-insertion (filename type description attributes) 230 (defun mh-mhn-compose-insertion (filename type description attributes)
203 "Add a directive to insert a MIME message part from a file. 231 "Add a directive to insert a MIME message part from a file.
204 This is the typical way to insert non-text parts in a message. 232 This is the typical way to insert non-text parts in a message.
284 "application/octet-stream" 312 "application/octet-stream"
285 description 313 description
286 "type=tar; conversions=x-compress" 314 "type=tar; conversions=x-compress"
287 "mode=image")) 315 "mode=image"))
288 316
289 317 ;;;###mh-autoload
290 (defun mh-mhn-compose-external-type (access-type host filename type 318 (defun mh-mhn-compose-external-type (access-type host filename type
291 &optional description 319 &optional description
292 attributes extra-params 320 attributes extra-params
293 comment) 321 comment)
294 "Add a directive to include a MIME reference to a remote file. 322 "Add a directive to include a MIME reference to a remote file.
299 file and TYPE which is the MIME Content-Type. Optional arguments include 327 file and TYPE which is the MIME Content-Type. Optional arguments include
300 DESCRIPTION, a line of text for the Content-description header, ATTRIBUTES, 328 DESCRIPTION, a line of text for the Content-description header, ATTRIBUTES,
301 EXTRA-PARAMS, and COMMENT. 329 EXTRA-PARAMS, and COMMENT.
302 330
303 See also \\[mh-edit-mhn]." 331 See also \\[mh-edit-mhn]."
332 (interactive (list
333 (completing-read "Access Type: " mh-access-types)
334 (read-string "Remote host: ")
335 (read-string "Remote url-path: ")
336 (completing-read "Content-Type: "
337 (if (fboundp 'mailcap-mime-types)
338 (mapcar 'list (mailcap-mime-types))
339 mh-mime-content-types))
340 (if current-prefix-arg (read-string "Content-description: "))
341 (if current-prefix-arg (read-string "Attributes: "))
342 (if current-prefix-arg (read-string "Extra Parameters: "))
343 (if current-prefix-arg (read-string "Comment: "))))
304 (beginning-of-line) 344 (beginning-of-line)
305 (insert "#@" type) 345 (insert "#@" type)
306 (and attributes 346 (and attributes
307 (insert "; " attributes)) 347 (insert "; " attributes))
308 (and comment 348 (and comment
312 (insert description)) 352 (insert description))
313 (insert "] ") 353 (insert "] ")
314 (insert "access-type=" access-type "; ") 354 (insert "access-type=" access-type "; ")
315 (insert "site=" host) 355 (insert "site=" host)
316 (insert "; name=" (file-name-nondirectory filename)) 356 (insert "; name=" (file-name-nondirectory filename))
317 (insert "; directory=\"" (file-name-directory filename) "\"") 357 (let ((directory (file-name-directory filename)))
358 (and directory
359 (insert "; directory=\"" directory "\"")))
318 (and extra-params 360 (and extra-params
319 (insert "; " extra-params)) 361 (insert "; " extra-params))
320 (insert "\n")) 362 (insert "\n"))
321 363
322 ;;;###mh-autoload 364 ;;;###mh-autoload
330 See also \\[mh-edit-mhn]." 372 See also \\[mh-edit-mhn]."
331 (interactive (list 373 (interactive (list
332 (read-string "Forw Content-description: ") 374 (read-string "Forw Content-description: ")
333 (mh-prompt-for-folder "Message from" mh-sent-from-folder nil) 375 (mh-prompt-for-folder "Message from" mh-sent-from-folder nil)
334 (read-string (format "Messages%s: " 376 (read-string (format "Messages%s: "
335 (if mh-sent-from-msg 377 (if (numberp mh-sent-from-msg)
336 (format " [%d]" mh-sent-from-msg) 378 (format " [%d]" mh-sent-from-msg)
337 ""))))) 379 "")))))
338 (beginning-of-line) 380 (beginning-of-line)
339 (insert "#forw [") 381 (insert "#forw [")
340 (and description 382 (and description
347 (if (and messages 389 (if (and messages
348 (not (string= messages ""))) 390 (not (string= messages "")))
349 (let ((start (point))) 391 (let ((start (point)))
350 (insert " " messages) 392 (insert " " messages)
351 (subst-char-in-region start (point) ?, ? )) 393 (subst-char-in-region start (point) ?, ? ))
352 (if mh-sent-from-msg 394 (if (numberp mh-sent-from-msg)
353 (insert " " (int-to-string mh-sent-from-msg)))) 395 (insert " " (int-to-string mh-sent-from-msg))))
354 (insert "\n")) 396 (insert "\n"))
355 397
356 ;;;###mh-autoload 398 ;;;###mh-autoload
357 (defun mh-edit-mhn (&optional extra-args) 399 (defun mh-edit-mhn (&optional extra-args)
378 The value of `mh-edit-mhn-hook' is a list of functions to be called, with no 420 The value of `mh-edit-mhn-hook' is a list of functions to be called, with no
379 arguments, after performing the conversion. 421 arguments, after performing the conversion.
380 422
381 The mhn program is part of MH version 6.8 or later." 423 The mhn program is part of MH version 6.8 or later."
382 (interactive "*P") 424 (interactive "*P")
425 (mh-mhn-quote-unescaped-sharp)
383 (save-buffer) 426 (save-buffer)
384 (message "mhn editing...") 427 (message "mhn editing...")
385 (cond 428 (cond
386 (mh-nmh-flag 429 ((mh-variant-p 'nmh)
387 (mh-exec-cmd-error nil 430 (mh-exec-cmd-error nil
388 "mhbuild" (if extra-args mh-mhn-args) buffer-file-name)) 431 "mhbuild" (if extra-args mh-mhn-args) buffer-file-name))
389 (t 432 (t
390 (mh-exec-cmd-error (format "mhdraft=%s" buffer-file-name) 433 (mh-exec-cmd-error (format "mhdraft=%s" buffer-file-name)
391 "mhn" (if extra-args mh-mhn-args) buffer-file-name))) 434 "mhn" (if extra-args mh-mhn-args) buffer-file-name)))
392 (revert-buffer t t) 435 (revert-buffer t t)
393 (message "mhn editing...done") 436 (message "mhn editing...done")
394 (run-hooks 'mh-edit-mhn-hook)) 437 (run-hooks 'mh-edit-mhn-hook))
438
439 (defun mh-mhn-quote-unescaped-sharp ()
440 "Quote `#' characters that haven't been quoted for `mhbuild'.
441 If the `#' character is present in the first column, but it isn't part of a
442 MHN directive then `mhbuild' gives an error. This function will quote all such
443 characters."
444 (save-excursion
445 (goto-char (point-min))
446 (while (re-search-forward "^#" nil t)
447 (beginning-of-line)
448 (unless (mh-mhn-directive-present-p (point) (line-end-position))
449 (insert "#"))
450 (goto-char (line-end-position)))))
395 451
396 ;;;###mh-autoload 452 ;;;###mh-autoload
397 (defun mh-revert-mhn-edit (noconfirm) 453 (defun mh-revert-mhn-edit (noconfirm)
398 "Undo the effect of \\[mh-edit-mhn] by reverting to the backup file. 454 "Undo the effect of \\[mh-edit-mhn] by reverting to the backup file.
399 Optional non-nil argument NOCONFIRM means don't ask for confirmation." 455 Optional non-nil argument NOCONFIRM means don't ask for confirmation."
420 (erase-buffer) 476 (erase-buffer)
421 (insert-file-contents backup-file)) 477 (insert-file-contents backup-file))
422 (after-find-file nil))) 478 (after-find-file nil)))
423 479
424 ;;;###mh-autoload 480 ;;;###mh-autoload
425 (defun mh-mhn-directive-present-p () 481 (defun mh-mhn-directive-present-p (&optional begin end)
426 "Check if the current buffer has text which might be a MHN directive." 482 "Check if the text between BEGIN and END might be a MHN directive.
483 The optional argument BEGIN defaults to the beginning of the buffer, while END
484 defaults to the the end of the buffer."
485 (unless begin (setq begin (point-min)))
486 (unless end (setq end (point-max)))
427 (save-excursion 487 (save-excursion
428 (block 'search-for-mhn-directive 488 (block 'search-for-mhn-directive
429 (goto-char (point-min)) 489 (goto-char begin)
430 (while (re-search-forward "^#" nil t) 490 (while (re-search-forward "^#" end t)
431 (let ((s (buffer-substring-no-properties (point) (line-end-position)))) 491 (let ((s (buffer-substring-no-properties (point) (line-end-position))))
432 (cond ((equal s "")) 492 (cond ((equal s ""))
433 ((string-match "^forw[ \t\n]+" s) 493 ((string-match "^forw[ \t\n]+" s)
434 (return-from 'search-for-mhn-directive t)) 494 (return-from 'search-for-mhn-directive t))
435 (t (let ((first-token (car (split-string s "[ \t;@]")))) 495 (t (let ((first-token (car (split-string s "[ \t;@]"))))
436 (when (string-match mh-media-type-regexp first-token) 496 (when (and first-token
497 (string-match mh-media-type-regexp
498 first-token))
437 (return-from 'search-for-mhn-directive t))))))) 499 (return-from 'search-for-mhn-directive t)))))))
438 nil))) 500 nil)))
439 501
440 502
441 503
448 function may be called manually before sending the draft as well." 510 function may be called manually before sending the draft as well."
449 (interactive) 511 (interactive)
450 (require 'message) 512 (require 'message)
451 (when mh-gnus-pgp-support-flag ;; This is only needed for PGP 513 (when mh-gnus-pgp-support-flag ;; This is only needed for PGP
452 (message-options-set-recipient)) 514 (message-options-set-recipient))
453 (mml-to-mime)) 515 (let ((saved-text (buffer-string))
516 (buffer (current-buffer))
517 (modified-flag (buffer-modified-p)))
518 (condition-case err (mml-to-mime)
519 (error
520 (with-current-buffer buffer
521 (delete-region (point-min) (point-max))
522 (insert saved-text)
523 (set-buffer-modified-p modified-flag))
524 (error (error-message-string err))))))
454 525
455 ;;;###mh-autoload 526 ;;;###mh-autoload
456 (defun mh-mml-forward-message (description folder message) 527 (defun mh-mml-forward-message (description folder message)
457 "Forward a message as attachment. 528 "Forward a message as attachment.
458 The function will prompt the user for a DESCRIPTION, a FOLDER and MESSAGE 529 The function will prompt the user for a DESCRIPTION, a FOLDER and MESSAGE
459 number." 530 number."
460 (let ((msg (if (equal message "") 531 (let ((msg (if (and (equal message "") (numberp mh-sent-from-msg))
461 mh-sent-from-msg 532 mh-sent-from-msg
462 (car (read-from-string message))))) 533 (car (read-from-string message)))))
463 (cond ((integerp msg) 534 (cond ((integerp msg)
464 (if (string= "" description) 535 (if (string= "" description)
465 ;; Rationale: mml-attach-file constructs a malformed composition 536 ;; Rationale: mml-attach-file constructs a malformed composition
470 (mml-attach-file (format "%s%s/%d" 541 (mml-attach-file (format "%s%s/%d"
471 mh-user-path (substring folder 1) msg) 542 mh-user-path (substring folder 1) msg)
472 "message/rfc822" 543 "message/rfc822"
473 description))) 544 description)))
474 (t (error "The message number, %s is not a integer!" msg))))) 545 (t (error "The message number, %s is not a integer!" msg)))))
546
547 (defvar mh-mml-cryptographic-method-history ())
548
549 ;;;###mh-autoload
550 (defun mh-mml-query-cryptographic-method ()
551 "Read the cryptographic method to use."
552 (if current-prefix-arg
553 (let ((def (or (car mh-mml-cryptographic-method-history)
554 mh-mml-method-default)))
555 (completing-read (format "Method: [%s] " def)
556 '(("pgp") ("pgpmime") ("smime"))
557 nil t nil 'mh-mml-cryptographic-method-history def))
558 mh-mml-method-default))
475 559
476 ;;;###mh-autoload 560 ;;;###mh-autoload
477 (defun mh-mml-attach-file (&optional disposition) 561 (defun mh-mml-attach-file (&optional disposition)
478 "Attach a file to the outgoing MIME message. 562 "Attach a file to the outgoing MIME message.
479 The file is not inserted or encoded until you send the message with 563 The file is not inserted or encoded until you send the message with
497 nil t nil nil 581 nil t nil nil
498 "attachment")))) 582 "attachment"))))
499 (mml-insert-empty-tag 'part 'type type 'filename file 583 (mml-insert-empty-tag 'part 'type type 'filename file
500 'disposition dispos 'description description))) 584 'disposition dispos 'description description)))
501 585
502 ;;;###mh-autoload 586 (defvar mh-identity-pgg-default-user-id)
503 (defun mh-mml-secure-message-sign-pgpmime () 587
504 "Add directive to encrypt/sign the entire message." 588 (defun mh-secure-message (method mode &optional identity)
505 (interactive) 589 "Add directive to Encrypt/Sign an entire message.
590 METHOD should be one of: \"pgpmime\", \"pgp\", \"smime\".
591 MODE should be one of: \"sign\", \"encrypt\", \"signencrypt\", \"none\".
592 IDENTITY is optionally the default-user-id to use."
506 (if (not mh-gnus-pgp-support-flag) 593 (if (not mh-gnus-pgp-support-flag)
507 (error "Sorry. Your version of gnus does not support PGP/GPG") 594 (error "Sorry. Your version of gnus does not support PGP/GPG")
508 (mml-secure-message-sign-pgpmime))) 595 ;; Check the arguments
509 596 (let ((valid-methods (list "pgpmime" "pgp" "smime"))
510 ;;;###mh-autoload 597 (valid-modes (list "sign" "encrypt" "signencrypt" "none")))
511 (defun mh-mml-secure-message-encrypt-pgpmime (&optional dontsign) 598 (if (not (member method valid-methods))
512 "Add directive to encrypt and sign the entire message. 599 (error (format "Sorry. METHOD \"%s\" is invalid." method)))
513 If called with a prefix argument DONTSIGN, only encrypt (do NOT sign)." 600 (if (not (member mode valid-modes))
601 (error (format "Sorry. MODE \"%s\" is invalid" mode)))
602 (mml-unsecure-message)
603 (if (not (string= mode "none"))
604 (save-excursion
605 (goto-char (point-min))
606 (mh-goto-header-end 1)
607 (if mh-identity-pgg-default-user-id
608 (mml-insert-tag 'secure 'method method 'mode mode
609 'sender mh-identity-pgg-default-user-id)
610 (mml-insert-tag 'secure 'method method 'mode mode)))))))
611
612 ;;;###mh-autoload
613 (defun mh-mml-unsecure-message (&optional ignore)
614 "Remove any secure message directives.
615 The IGNORE argument is not used."
514 (interactive "P") 616 (interactive "P")
515 (if (not mh-gnus-pgp-support-flag) 617 (if (not mh-gnus-pgp-support-flag)
516 (error "Sorry. Your version of gnus does not support PGP/GPG") 618 (error "Sorry. Your version of gnus does not support PGP/GPG")
517 (mml-secure-message-encrypt-pgpmime dontsign))) 619 (mml-unsecure-message)))
620
621 ;;;###mh-autoload
622 (defun mh-mml-secure-message-sign (method)
623 "Add security directive to sign the entire message using METHOD."
624 (interactive (list (mh-mml-query-cryptographic-method)))
625 (mh-secure-message method "sign" mh-identity-pgg-default-user-id))
626
627 ;;;###mh-autoload
628 (defun mh-mml-secure-message-encrypt (method)
629 "Add security directive to encrypt the entire message using METHOD."
630 (interactive (list (mh-mml-query-cryptographic-method)))
631 (mh-secure-message method "encrypt" mh-identity-pgg-default-user-id))
632
633 ;;;###mh-autoload
634 (defun mh-mml-secure-message-signencrypt (method)
635 "Add security directive to encrypt and sign the entire message using METHOD."
636 (interactive (list (mh-mml-query-cryptographic-method)))
637 (mh-secure-message method "signencrypt" mh-identity-pgg-default-user-id))
518 638
519 ;;;###mh-autoload 639 ;;;###mh-autoload
520 (defun mh-mml-directive-present-p () 640 (defun mh-mml-directive-present-p ()
521 "Check if the current buffer has text which may be an MML directive." 641 "Check if the current buffer has text which may be an MML directive."
522 (save-excursion 642 (save-excursion
665 (mh-show-buffer-message-number) 785 (mh-show-buffer-message-number)
666 (mh-get-msg-num t))) 786 (mh-get-msg-num t)))
667 (folder (if (eq major-mode 'mh-show-mode) 787 (folder (if (eq major-mode 'mh-show-mode)
668 mh-show-folder-buffer 788 mh-show-folder-buffer
669 mh-current-folder)) 789 mh-current-folder))
670 (command (if mh-nmh-flag "mhstore" "mhn")) 790 (command (if (mh-variant-p 'nmh) "mhstore" "mhn"))
671 (directory 791 (directory
672 (cond 792 (cond
673 ((and (or arg 793 ((and (or arg
674 (equal nil mh-mime-save-parts-default-directory) 794 (equal nil mh-mime-save-parts-default-directory)
675 (equal t mh-mime-save-parts-default-directory)) 795 (equal t mh-mime-save-parts-default-directory))
676 (not mh-mime-save-parts-directory)) 796 (not mh-mime-save-parts-directory))
677 (read-file-name "Store in what directory? " nil nil t nil)) 797 (read-file-name "Store in directory: " nil nil t nil))
678 ((and (or arg 798 ((and (or arg
679 (equal t mh-mime-save-parts-default-directory)) 799 (equal t mh-mime-save-parts-default-directory))
680 mh-mime-save-parts-directory) 800 mh-mime-save-parts-directory)
681 (read-file-name (format 801 (read-file-name (format
682 "Store in what directory? [%s] " 802 "Store in directory: [%s] "
683 mh-mime-save-parts-directory) 803 mh-mime-save-parts-directory)
684 "" mh-mime-save-parts-directory t "")) 804 "" mh-mime-save-parts-directory t ""))
685 ((stringp mh-mime-save-parts-default-directory) 805 ((stringp mh-mime-save-parts-default-directory)
686 mh-mime-save-parts-default-directory) 806 mh-mime-save-parts-default-directory)
687 (t 807 (t
688 mh-mime-save-parts-directory)))) 808 mh-mime-save-parts-directory))))
689 (if (and (equal directory "") mh-mime-save-parts-directory) 809 (if (and (equal directory "") mh-mime-save-parts-directory)
690 (setq directory mh-mime-save-parts-directory)) 810 (setq directory mh-mime-save-parts-directory))
691 (if (not (file-directory-p directory)) 811 (if (not (file-directory-p directory))
692 (message "No directory specified.") 812 (message "No directory specified")
693 (if (equal nil mh-mime-save-parts-default-directory) 813 (if (equal nil mh-mime-save-parts-default-directory)
694 (setq mh-mime-save-parts-directory directory)) 814 (setq mh-mime-save-parts-directory directory))
695 (save-excursion 815 (save-excursion
696 (set-buffer (get-buffer-create mh-log-buffer)) 816 (set-buffer (get-buffer-create mh-log-buffer))
697 (cd directory) 817 (cd directory)
730 (and cte (intern (downcase 850 (and cte (intern (downcase
731 (gnus-strip-whitespace cte)))) 851 (gnus-strip-whitespace cte))))
732 (car ct)))))) 852 (car ct))))))
733 853
734 ;;;###mh-autoload 854 ;;;###mh-autoload
855 (defun mh-toggle-mh-decode-mime-flag ()
856 "Toggle whether MH-E should decode MIME or not."
857 (interactive)
858 (setq mh-decode-mime-flag (not mh-decode-mime-flag))
859 (mh-show nil t)
860 (message (format "(setq mh-decode-mime-flag %s)" mh-decode-mime-flag)))
861
862 ;;;###mh-autoload
735 (defun mh-decode-message-header () 863 (defun mh-decode-message-header ()
736 "Decode RFC2047 encoded message header fields." 864 "Decode RFC2047 encoded message header fields."
737 (when mh-decode-mime-flag 865 (when mh-decode-mime-flag
738 (let ((buffer-read-only nil)) 866 (let ((buffer-read-only nil))
739 (rfc2047-decode-region (point-min) (mh-mail-header-end))))) 867 (rfc2047-decode-region (point-min) (mh-mail-header-end)))))
764 (setf (mh-mime-handles (mh-buffer-data)) 892 (setf (mh-mime-handles (mh-buffer-data))
765 (mm-merge-handles handles 893 (mm-merge-handles handles
766 (mh-mime-handles (mh-buffer-data)))) 894 (mh-mime-handles (mh-buffer-data))))
767 (unless handles (mh-decode-message-body))) 895 (unless handles (mh-decode-message-body)))
768 896
769 (when (and handles 897 (cond ((and handles
770 (or (not (stringp (car handles))) (cdr handles))) 898 (or (not (stringp (car handles))) (cdr handles)))
771 ;; Goto start of message body 899 ;; Goto start of message body
772 (goto-char (point-min)) 900 (goto-char (point-min))
773 (or (search-forward "\n\n" nil t) (goto-char (point-max))) 901 (or (search-forward "\n\n" nil t) (goto-char (point-max)))
774 902
775 ;; Delete the body 903 ;; Delete the body
776 (delete-region (point) (point-max)) 904 (delete-region (point) (point-max))
777 905
778 ;; Display the MIME handles 906 ;; Display the MIME handles
779 (mh-mime-display-part handles))) 907 (mh-mime-display-part handles))
908 (t (mh-signature-highlight))))
780 (error 909 (error
781 (message "Please report this error. The error message is:\n %s" 910 (message "Please report this error. The error message is:\n %s"
782 (error-message-string err)) 911 (error-message-string err))
783 (delete-region (point-min) (point-max)) 912 (delete-region (point-min) (point-max))
784 (insert raw-message-data)))))) 913 (insert raw-message-data))))))
872 (equal (car type) "text/x-vcard") 1001 (equal (car type) "text/x-vcard")
873 (save-excursion 1002 (save-excursion
874 (save-restriction 1003 (save-restriction
875 (widen) 1004 (widen)
876 (goto-char (point-min)) 1005 (goto-char (point-min))
877 (not (re-search-forward "^-- $" nil t))))))) 1006 (not (mh-signature-separator-p)))))))
878 1007
879 (defun mh-mime-display-single (handle) 1008 (defun mh-mime-display-single (handle)
880 "Display a leaf node, HANDLE in the MIME tree." 1009 "Display a leaf node, HANDLE in the MIME tree."
881 (let* ((type (mm-handle-media-type handle)) 1010 (let* ((type (mm-handle-media-type handle))
882 (small-image-flag (mh-small-image-p handle)) 1011 (small-image-flag (mh-small-image-p handle))
902 nil) ; skip signatures as they are already handled... 1031 nil) ; skip signatures as they are already handled...
903 ((not displayp) 1032 ((not displayp)
904 (insert "\n") 1033 (insert "\n")
905 (mh-insert-mime-button handle (mh-mime-part-index handle) nil)) 1034 (mh-insert-mime-button handle (mh-mime-part-index handle) nil))
906 ((and displayp (not mh-display-buttons-for-inline-parts-flag)) 1035 ((and displayp (not mh-display-buttons-for-inline-parts-flag))
907 (or (mm-display-part handle) (mm-display-part handle))) 1036 (or (mm-display-part handle) (mm-display-part handle))
1037 (mh-signature-highlight handle))
908 ((and displayp mh-display-buttons-for-inline-parts-flag) 1038 ((and displayp mh-display-buttons-for-inline-parts-flag)
909 (insert "\n") 1039 (insert "\n")
910 (mh-insert-mime-button handle (mh-mime-part-index handle) nil) 1040 (mh-insert-mime-button handle (mh-mime-part-index handle) nil)
911 (forward-line -1) 1041 (forward-line -1)
912 (mh-mm-display-part handle))) 1042 (mh-mm-display-part handle)))
913 (goto-char (point-max))))) 1043 (goto-char (point-max)))))
1044
1045 (defun mh-signature-highlight (&optional handle)
1046 "Highlight message signature in HANDLE.
1047 The optional argument, HANDLE is a MIME handle if the function is being used
1048 to highlight the signature in a MIME part."
1049 (let ((regexp
1050 (cond ((not handle) "^-- $")
1051 ((not (and (equal (mm-handle-media-supertype handle) "text")
1052 (equal (mm-handle-media-subtype handle) "html")))
1053 "^-- $")
1054 ((eq (mh-mm-text-html-renderer) 'lynx) "^ --$")
1055 (t "^--$"))))
1056 (save-excursion
1057 (goto-char (point-max))
1058 (when (re-search-backward regexp nil t)
1059 (mh-do-in-gnu-emacs
1060 (let ((ov (make-overlay (point) (point-max))))
1061 (overlay-put ov 'face 'mh-show-signature-face)
1062 (overlay-put ov 'evaporate t)))
1063 (mh-do-in-xemacs
1064 (set-extent-property (make-extent (point) (point-max))
1065 'face 'mh-show-signature-face))))))
914 1066
915 (mh-do-in-xemacs 1067 (mh-do-in-xemacs
916 (defvar dots) 1068 (defvar dots)
917 (defvar type)) 1069 (defvar type))
918 1070
952 'link begin end 1104 'link begin end
953 :mime-handle handle 1105 :mime-handle handle
954 :action 'mh-widget-press-button 1106 :action 'mh-widget-press-button
955 :button-keymap mh-mime-button-map 1107 :button-keymap mh-mime-button-map
956 :help-echo 1108 :help-echo
957 "Mouse-2 click or press RET (in show buffer) to toggle display"))) 1109 "Mouse-2 click or press RET (in show buffer) to toggle display")
1110 (dolist (ov (mh-funcall-if-exists overlays-in begin end))
1111 (mh-funcall-if-exists overlay-put ov 'evaporate t))))
958 1112
959 ;; There is a bug in Gnus inline image display due to which an extra line 1113 ;; There is a bug in Gnus inline image display due to which an extra line
960 ;; gets inserted every time it is viewed. To work around that problem we are 1114 ;; gets inserted every time it is viewed. To work around that problem we are
961 ;; using an extra property 'mh-region to remember the region that is added 1115 ;; using an extra property 'mh-region to remember the region that is added
962 ;; when the button is clicked. The region is then deleted to make sure that 1116 ;; when the button is clicked. The region is then deleted to make sure that
1007 (delete-char 1)) 1161 (delete-char 1))
1008 (when (equal (mm-handle-media-supertype handle) "text") 1162 (when (equal (mm-handle-media-supertype handle) "text")
1009 (when (eq mh-highlight-citation-p 'gnus) 1163 (when (eq mh-highlight-citation-p 'gnus)
1010 (mh-gnus-article-highlight-citation)) 1164 (mh-gnus-article-highlight-citation))
1011 (mh-display-smileys) 1165 (mh-display-smileys)
1012 (mh-display-emphasis)) 1166 (mh-display-emphasis)
1167 (mh-signature-highlight handle))
1013 (setq region (cons (progn (goto-char (point-min)) 1168 (setq region (cons (progn (goto-char (point-min))
1014 (point-marker)) 1169 (point-marker))
1015 (progn (goto-char (point-max)) 1170 (progn (goto-char (point-max))
1016 (point-marker))))))) 1171 (point-marker)))))))
1017 (when (window-live-p window) 1172 (when (window-live-p window)
1096 (mh-press-button) 1251 (mh-press-button)
1097 (message "MIME part already inserted"))) 1252 (message "MIME part already inserted")))
1098 (goto-char point) 1253 (goto-char point)
1099 (set-buffer-modified-p nil))) 1254 (set-buffer-modified-p nil)))
1100 1255
1256 ;;;###mh-autoload
1257 (defun mh-display-with-external-viewer (part-index)
1258 "View MIME PART-INDEX externally."
1259 (interactive "P")
1260 (when (consp part-index) (setq part-index (car part-index)))
1261 (mh-folder-mime-action
1262 part-index
1263 #'(lambda ()
1264 (let* ((part (get-text-property (point) 'mh-data))
1265 (type (mm-handle-media-type part))
1266 (methods (mapcar (lambda (x) (list (cdr (assoc 'viewer x))))
1267 (mailcap-mime-info type 'all)))
1268 (def (caar methods))
1269 (prompt (format "Viewer: %s" (if def (format "[%s] " def) "")))
1270 (method (completing-read prompt methods nil nil nil nil def))
1271 (folder mh-show-folder-buffer)
1272 (buffer-read-only nil))
1273 (when (string-match "^[^% \t]+$" method)
1274 (setq method (concat method " %s")))
1275 (flet ((mm-handle-set-external-undisplayer (handle function)
1276 (mh-handle-set-external-undisplayer folder handle function)))
1277 (unwind-protect (mm-display-external part method)
1278 (set-buffer-modified-p nil)))))
1279 nil))
1280
1101 (defun mh-widget-press-button (widget el) 1281 (defun mh-widget-press-button (widget el)
1102 "Callback for widget, WIDGET. 1282 "Callback for widget, WIDGET.
1103 Parameter EL is unused." 1283 Parameter EL is unused."
1104 (goto-char (widget-get widget :from)) 1284 (goto-char (widget-get widget :from))
1105 (mh-press-button)) 1285 (mh-press-button))
1106 1286
1107 (defun mh-mime-display-security (handle) 1287 (defun mh-mime-display-security (handle)
1108 "Display PGP encrypted/signed message, HANDLE." 1288 "Display PGP encrypted/signed message, HANDLE."
1109 (insert "\n")
1110 (save-restriction 1289 (save-restriction
1111 (narrow-to-region (point) (point)) 1290 (narrow-to-region (point) (point))
1291 (insert "\n")
1112 (mh-insert-mime-security-button handle) 1292 (mh-insert-mime-security-button handle)
1113 (mh-mime-display-mixed (cdr handle)) 1293 (mh-mime-display-mixed (cdr handle))
1114 (insert "\n") 1294 (insert "\n")
1115 (let ((mh-mime-security-button-line-format 1295 (let ((mh-mime-security-button-line-format
1116 mh-mime-security-button-end-line-format)) 1296 mh-mime-security-button-end-line-format))
1117 (mh-insert-mime-security-button handle)) 1297 (mh-insert-mime-security-button handle))
1118 (mm-set-handle-multipart-parameter 1298 (mm-set-handle-multipart-parameter
1119 handle 'mh-region 1299 handle 'mh-region (cons (point-min-marker) (point-max-marker)))))
1120 (cons (set-marker (make-marker) (point-min))
1121 (set-marker (make-marker) (point-max))))))
1122 1300
1123 ;;; I rewrote the security part because Gnus doesn't seem to ever minimize 1301 ;;; I rewrote the security part because Gnus doesn't seem to ever minimize
1124 ;;; the button. That is once the mime-security button is pressed there seems 1302 ;;; the button. That is once the mime-security button is pressed there seems
1125 ;;; to be no way of getting rid of the inserted text. 1303 ;;; to be no way of getting rid of the inserted text.
1126 (defun mh-mime-security-show-details (handle) 1304 (defun mh-mime-security-show-details (handle)
1147 (point-max))) 1325 (point-max)))
1148 (forward-line -1))))) 1326 (forward-line -1)))))
1149 1327
1150 (defun mh-mime-security-press-button (handle) 1328 (defun mh-mime-security-press-button (handle)
1151 "Callback from security button for part HANDLE." 1329 "Callback from security button for part HANDLE."
1152 (when (mm-handle-multipart-ctl-parameter handle 'gnus-info) 1330 (if (mm-handle-multipart-ctl-parameter handle 'gnus-info)
1153 (mh-mime-security-show-details handle))) 1331 (mh-mime-security-show-details handle)
1332 (let ((region (mm-handle-multipart-ctl-parameter handle 'mh-region))
1333 point)
1334 (setq point (point))
1335 (goto-char (car region))
1336 (delete-region (car region) (cdr region))
1337 (with-current-buffer (mm-handle-multipart-ctl-parameter handle 'buffer)
1338 (let* ((mm-verify-option 'known)
1339 (mm-decrypt-option 'known)
1340 (new (mm-possibly-verify-or-decrypt (cdr handle) handle)))
1341 (unless (eq new (cdr handle))
1342 (mm-destroy-parts (cdr handle))
1343 (setcdr handle new))))
1344 (mh-mime-display-security handle)
1345 (goto-char point))))
1154 1346
1155 ;; These variables should already be initialized in mm-decode.el if we have a 1347 ;; These variables should already be initialized in mm-decode.el if we have a
1156 ;; recent enough Gnus. The defvars are here to avoid compiler warnings. 1348 ;; recent enough Gnus. The defvars are here to avoid compiler warnings.
1157 (defvar mm-verify-function-alist nil) 1349 (defvar mm-verify-function-alist nil)
1158 (defvar mm-decrypt-function-alist nil) 1350 (defvar mm-decrypt-function-alist nil)
1189 (widget-convert-button 'link begin end 1381 (widget-convert-button 'link begin end
1190 :mime-handle handle 1382 :mime-handle handle
1191 :action 'mh-widget-press-button 1383 :action 'mh-widget-press-button
1192 :button-keymap mh-mime-security-button-map 1384 :button-keymap mh-mime-security-button-map
1193 :help-echo "Mouse-2 click or press RET (in show buffer) to see security details.") 1385 :help-echo "Mouse-2 click or press RET (in show buffer) to see security details.")
1386 (dolist (ov (mh-funcall-if-exists overlays-in begin end))
1387 (mh-funcall-if-exists overlay-put ov 'evaporate t))
1194 (when (equal info "Failed") 1388 (when (equal info "Failed")
1195 (let* ((type (if (equal (car handle) "multipart/signed") 1389 (let* ((type (if (equal (car handle) "multipart/signed")
1196 "verification" "decryption")) 1390 "verification" "decryption"))
1197 (warning (if (equal type "decryption") 1391 (warning (if (equal type "decryption")
1198 "(passphrase may be incorrect)" ""))) 1392 "(passphrase may be incorrect)" "")))
1202 "Display message, HANDLE. 1396 "Display message, HANDLE.
1203 The function decodes the message and displays it. It avoids decoding the same 1397 The function decodes the message and displays it. It avoids decoding the same
1204 message multiple times." 1398 message multiple times."
1205 (let ((b (point)) 1399 (let ((b (point))
1206 (clean-message-header mh-clean-message-header-flag) 1400 (clean-message-header mh-clean-message-header-flag)
1207 (invisible-headers mh-invisible-headers) 1401 (invisible-headers mh-invisible-header-fields-compiled)
1208 (visible-headers mh-visible-headers)) 1402 (visible-headers nil))
1209 (save-excursion 1403 (save-excursion
1210 (save-restriction 1404 (save-restriction
1211 (narrow-to-region b b) 1405 (narrow-to-region b b)
1212 (mm-insert-part handle) 1406 (mm-insert-part handle)
1213 (mh-mime-display 1407 (mh-mime-display