comparison lisp/gnus/mml2015.el @ 110583:b6d2a63ad993

Merge changes made in Gnus trunk. nnimap.el: Implement partial IMAP article fetch. nnimap.el: Have nnimap not update the infos if it can't get info from the server. Implement functions for showing the complete articles. gnus-int.el (gnus-open-server): Don't query whether to go offline -- just do it. gnus-art.el (gnus-mime-delete-part): Fix plural for "byte" when there isn't a single byte. nndoc.el (nndoc-type-alist): Move mime-parts after mbox. Suggested by Jay Berkenbilt. mm-decode.el (mm-save-part): Allow saving to other directories the normal Emacs way. gnus-html.el (gnus-html-rescale-image): Use our defalias gnus-window-inside-pixel-edges. gnus-srvr.el (gnus-server-copy-server): Add documentation. gnus.texi (Using IMAP): Document the new nnimap. nnimap.el (nnimap-wait-for-response): Search further when we're not using streaming. gnus-int.el (gnus-check-server): Say what the error was when opening failed. nnheader.el (nnheader-get-report-string): New function. gnus-int.el (gnus-check-server): Use report-string. nnimap.el (nnimap-open-connection): Add more error reporting when nnimap fails early. gnus-start.el (gnus-get-unread-articles): Don't try to open failed servers twice. nnimap.el (nnimap-wait-for-response): Reversed logic in the nnimap-streaming test. gnus-art.el: Removed CTAN button stuff, which I don't think is very relevant any more. Remove NoCeM support, since nobody seems to use it any more. Remove earcon and gnus-audio. gnus.el (gnus): Silence gnus-load message. gnus-group.el (gnus-read-ephemeral-bug-group): Add the bug email address to the To list for easier response. gnus.texi (Connecting to an IMAP Server): Show how to use as primary method instead of secondary.
author Katsumi Yamaoka <yamaoka@jpl.org>
date Sun, 26 Sep 2010 04:03:19 +0000
parents f567b340d004
children 6c6f3972c99c
comparison
equal deleted inserted replaced
110582:aa7656773a38 110583:b6d2a63ad993
61 ;; in Emacs 21.1. 61 ;; in Emacs 21.1.
62 (let ((recursive-load-depth-limit 100)) 62 (let ((recursive-load-depth-limit 100))
63 (require 'pgg))) 63 (require 'pgg)))
64 (and (fboundp 'pgg-sign-region) 64 (and (fboundp 'pgg-sign-region)
65 'pgg)) 65 'pgg))
66 (progn
67 (ignore-errors
68 (require 'gpg))
69 (and (fboundp 'gpg-sign-detached)
70 'gpg))
71 (progn (ignore-errors 66 (progn (ignore-errors
72 (load "mc-toplev")) 67 (load "mc-toplev"))
73 (and (fboundp 'mc-encrypt-generic) 68 (and (fboundp 'mc-encrypt-generic)
74 (fboundp 'mc-sign-generic) 69 (fboundp 'mc-sign-generic)
75 (fboundp 'mc-cleanup-recipient-headers) 70 (fboundp 'mc-cleanup-recipient-headers)
76 'mailcrypt))) 71 'mailcrypt)))
77 "The package used for PGP/MIME. 72 "The package used for PGP/MIME.
78 Valid packages include `epg', `pgg', `gpg' and `mailcrypt'.") 73 Valid packages include `epg', `pgg' and `mailcrypt'.")
79 74
80 ;; Something is not RFC2015. 75 ;; Something is not RFC2015.
81 (defvar mml2015-function-alist 76 (defvar mml2015-function-alist
82 '((mailcrypt mml2015-mailcrypt-sign 77 '((mailcrypt mml2015-mailcrypt-sign
83 mml2015-mailcrypt-encrypt 78 mml2015-mailcrypt-encrypt
84 mml2015-mailcrypt-verify 79 mml2015-mailcrypt-verify
85 mml2015-mailcrypt-decrypt 80 mml2015-mailcrypt-decrypt
86 mml2015-mailcrypt-clear-verify 81 mml2015-mailcrypt-clear-verify
87 mml2015-mailcrypt-clear-decrypt) 82 mml2015-mailcrypt-clear-decrypt)
88 (gpg mml2015-gpg-sign 83 (pgg mml2015-pgg-sign
89 mml2015-gpg-encrypt 84 mml2015-pgg-encrypt
90 mml2015-gpg-verify 85 mml2015-pgg-verify
91 mml2015-gpg-decrypt 86 mml2015-pgg-decrypt
92 mml2015-gpg-clear-verify 87 mml2015-pgg-clear-verify
93 mml2015-gpg-clear-decrypt) 88 mml2015-pgg-clear-decrypt)
94 (pgg mml2015-pgg-sign 89 (epg mml2015-epg-sign
95 mml2015-pgg-encrypt 90 mml2015-epg-encrypt
96 mml2015-pgg-verify 91 mml2015-epg-verify
97 mml2015-pgg-decrypt 92 mml2015-epg-decrypt
98 mml2015-pgg-clear-verify 93 mml2015-epg-clear-verify
99 mml2015-pgg-clear-decrypt) 94 mml2015-epg-clear-decrypt))
100 (epg mml2015-epg-sign
101 mml2015-epg-encrypt
102 mml2015-epg-verify
103 mml2015-epg-decrypt
104 mml2015-epg-clear-verify
105 mml2015-epg-clear-decrypt))
106 "Alist of PGP/MIME functions.") 95 "Alist of PGP/MIME functions.")
107 96
108 (defvar mml2015-result-buffer nil) 97 (defvar mml2015-result-buffer nil)
109 98
110 (defcustom mml2015-unabbrev-trust-alist 99 (defcustom mml2015-unabbrev-trust-alist
146 :group 'mime-security 135 :group 'mime-security
147 :type 'boolean) 136 :type 'boolean)
148 137
149 ;; Extract plaintext from cleartext signature. IMO, this kind of task 138 ;; Extract plaintext from cleartext signature. IMO, this kind of task
150 ;; should be done by GnuPG rather than Elisp, but older PGP backends 139 ;; should be done by GnuPG rather than Elisp, but older PGP backends
151 ;; (such as Mailcrypt, PGG, and gpg.el) discard the output from GnuPG. 140 ;; (such as Mailcrypt, and PGG) discard the output from GnuPG.
152 (defun mml2015-extract-cleartext-signature () 141 (defun mml2015-extract-cleartext-signature ()
153 ;; Daiki Ueno in 142 ;; Daiki Ueno in
154 ;; <54a15d860801080142l70b95d7dkac4bf51a86196011@mail.gmail.com>: ``I still 143 ;; <54a15d860801080142l70b95d7dkac4bf51a86196011@mail.gmail.com>: ``I still
155 ;; believe that the right way is to use the plaintext output from GnuPG as 144 ;; believe that the right way is to use the plaintext output from GnuPG as
156 ;; it is, and mml2015-extract-cleartext-signature is just a kludge for 145 ;; it is, and mml2015-extract-cleartext-signature is just a kludge for
231 (mml2015-gpg-extract-signature-details)))) 220 (mml2015-gpg-extract-signature-details))))
232 (concat ", Signer: " sig)))) 221 (concat ", Signer: " sig))))
233 (if (listp (car handles)) 222 (if (listp (car handles))
234 handles 223 handles
235 (list handles))))) 224 (list handles)))))
225
226 (defun mml2015-gpg-pretty-print-fpr (fingerprint)
227 (let* ((result "")
228 (fpr-length (string-width fingerprint))
229 (n-slice 0)
230 slice)
231 (setq fingerprint (string-to-list fingerprint))
232 (while fingerprint
233 (setq fpr-length (- fpr-length 4))
234 (setq slice (butlast fingerprint fpr-length))
235 (setq fingerprint (nthcdr 4 fingerprint))
236 (setq n-slice (1+ n-slice))
237 (setq result
238 (concat
239 result
240 (case n-slice
241 (1 slice)
242 (otherwise (concat " " slice))))))
243 result))
244
245 (defun mml2015-gpg-extract-signature-details ()
246 (goto-char (point-min))
247 (let* ((expired (re-search-forward
248 "^\\[GNUPG:\\] SIGEXPIRED$"
249 nil t))
250 (signer (and (re-search-forward
251 "^\\[GNUPG:\\] GOODSIG \\([0-9A-Za-z]*\\) \\(.*\\)$"
252 nil t)
253 (cons (match-string 1) (match-string 2))))
254 (fprint (and (re-search-forward
255 "^\\[GNUPG:\\] VALIDSIG \\([0-9a-zA-Z]*\\) "
256 nil t)
257 (match-string 1)))
258 (trust (and (re-search-forward
259 "^\\[GNUPG:\\] \\(TRUST_.*\\)$"
260 nil t)
261 (match-string 1)))
262 (trust-good-enough-p
263 (cdr (assoc trust mml2015-unabbrev-trust-alist))))
264 (cond ((and signer fprint)
265 (concat (cdr signer)
266 (unless trust-good-enough-p
267 (concat "\nUntrusted, Fingerprint: "
268 (mml2015-gpg-pretty-print-fpr fprint)))
269 (when expired
270 (format "\nWARNING: Signature from expired key (%s)"
271 (car signer)))))
272 ((re-search-forward
273 "^\\(gpg: \\)?Good signature from \"\\(.*\\)\"$" nil t)
274 (match-string 2))
275 (t
276 "From unknown user"))))
236 277
237 (defun mml2015-mailcrypt-clear-decrypt () 278 (defun mml2015-mailcrypt-clear-decrypt ()
238 (let (result) 279 (let (result)
239 (setq result 280 (setq result
240 (condition-case err 281 (condition-case err
443 (insert (format "--%s\n" boundary)) 484 (insert (format "--%s\n" boundary))
444 (insert "Content-Type: application/octet-stream\n\n") 485 (insert "Content-Type: application/octet-stream\n\n")
445 (goto-char (point-max)) 486 (goto-char (point-max))
446 (insert (format "--%s--\n" boundary)) 487 (insert (format "--%s--\n" boundary))
447 (goto-char (point-max)))) 488 (goto-char (point-max))))
448
449 ;;; gpg wrapper
450
451 (autoload 'gpg-decrypt "gpg")
452 (autoload 'gpg-verify "gpg")
453 (autoload 'gpg-verify-cleartext "gpg")
454 (autoload 'gpg-sign-detached "gpg")
455 (autoload 'gpg-sign-encrypt "gpg")
456 (autoload 'gpg-encrypt "gpg")
457 (autoload 'gpg-passphrase-read "gpg")
458
459 (defun mml2015-gpg-passphrase ()
460 (or (message-options-get 'gpg-passphrase)
461 (message-options-set 'gpg-passphrase (gpg-passphrase-read))))
462
463 (defun mml2015-gpg-decrypt-1 ()
464 (let ((cipher (current-buffer)) plain result)
465 (if (with-temp-buffer
466 (prog1
467 (gpg-decrypt cipher (setq plain (current-buffer))
468 mml2015-result-buffer nil)
469 (mm-set-handle-multipart-parameter
470 mm-security-handle 'gnus-details
471 (with-current-buffer mml2015-result-buffer
472 (buffer-string)))
473 (set-buffer cipher)
474 (erase-buffer)
475 (insert-buffer-substring plain)
476 (goto-char (point-min))
477 (while (search-forward "\r\n" nil t)
478 (replace-match "\n" t t))))
479 '(t)
480 ;; Some wrong with the return value, check plain text buffer.
481 (if (> (point-max) (point-min))
482 '(t)
483 nil))))
484
485 (defun mml2015-gpg-decrypt (handle ctl)
486 (let ((mml2015-decrypt-function 'mml2015-gpg-decrypt-1))
487 (mml2015-mailcrypt-decrypt handle ctl)))
488
489 (defun mml2015-gpg-clear-decrypt ()
490 (let (result)
491 (setq result (mml2015-gpg-decrypt-1))
492 (if (car result)
493 (mm-set-handle-multipart-parameter
494 mm-security-handle 'gnus-info "OK")
495 (mm-set-handle-multipart-parameter
496 mm-security-handle 'gnus-info "Failed"))))
497
498 (defun mml2015-gpg-pretty-print-fpr (fingerprint)
499 (let* ((result "")
500 (fpr-length (string-width fingerprint))
501 (n-slice 0)
502 slice)
503 (setq fingerprint (string-to-list fingerprint))
504 (while fingerprint
505 (setq fpr-length (- fpr-length 4))
506 (setq slice (butlast fingerprint fpr-length))
507 (setq fingerprint (nthcdr 4 fingerprint))
508 (setq n-slice (1+ n-slice))
509 (setq result
510 (concat
511 result
512 (case n-slice
513 (1 slice)
514 (otherwise (concat " " slice))))))
515 result))
516
517 (defun mml2015-gpg-extract-signature-details ()
518 (goto-char (point-min))
519 (let* ((expired (re-search-forward
520 "^\\[GNUPG:\\] SIGEXPIRED$"
521 nil t))
522 (signer (and (re-search-forward
523 "^\\[GNUPG:\\] GOODSIG \\([0-9A-Za-z]*\\) \\(.*\\)$"
524 nil t)
525 (cons (match-string 1) (match-string 2))))
526 (fprint (and (re-search-forward
527 "^\\[GNUPG:\\] VALIDSIG \\([0-9a-zA-Z]*\\) "
528 nil t)
529 (match-string 1)))
530 (trust (and (re-search-forward
531 "^\\[GNUPG:\\] \\(TRUST_.*\\)$"
532 nil t)
533 (match-string 1)))
534 (trust-good-enough-p
535 (cdr (assoc trust mml2015-unabbrev-trust-alist))))
536 (cond ((and signer fprint)
537 (concat (cdr signer)
538 (unless trust-good-enough-p
539 (concat "\nUntrusted, Fingerprint: "
540 (mml2015-gpg-pretty-print-fpr fprint)))
541 (when expired
542 (format "\nWARNING: Signature from expired key (%s)"
543 (car signer)))))
544 ((re-search-forward
545 "^\\(gpg: \\)?Good signature from \"\\(.*\\)\"$" nil t)
546 (match-string 2))
547 (t
548 "From unknown user"))))
549
550 (defun mml2015-gpg-verify (handle ctl)
551 (catch 'error
552 (let (part message signature info-is-set-p)
553 (unless (setq part (mm-find-raw-part-by-type
554 ctl (or (mm-handle-multipart-ctl-parameter
555 ctl 'protocol)
556 "application/pgp-signature")
557 t))
558 (mm-set-handle-multipart-parameter
559 mm-security-handle 'gnus-info "Corrupted")
560 (throw 'error handle))
561 (with-temp-buffer
562 (setq message (current-buffer))
563 (insert part)
564 ;; Convert <LF> to <CR><LF> in signed text. If --textmode is
565 ;; specified when signing, the conversion is not necessary.
566 (goto-char (point-min))
567 (end-of-line)
568 (while (not (eobp))
569 (unless (eq (char-before) ?\r)
570 (insert "\r"))
571 (forward-line)
572 (end-of-line))
573 (with-temp-buffer
574 (setq signature (current-buffer))
575 (unless (setq part (mm-find-part-by-type
576 (cdr handle) "application/pgp-signature" nil t))
577 (mm-set-handle-multipart-parameter
578 mm-security-handle 'gnus-info "Corrupted")
579 (throw 'error handle))
580 (mm-insert-part part)
581 (unless (condition-case err
582 (prog1
583 (gpg-verify message signature mml2015-result-buffer)
584 (mm-set-handle-multipart-parameter
585 mm-security-handle 'gnus-details
586 (with-current-buffer mml2015-result-buffer
587 (buffer-string))))
588 (error
589 (mm-set-handle-multipart-parameter
590 mm-security-handle 'gnus-details (mml2015-format-error err))
591 (mm-set-handle-multipart-parameter
592 mm-security-handle 'gnus-info "Error.")
593 (setq info-is-set-p t)
594 nil)
595 (quit
596 (mm-set-handle-multipart-parameter
597 mm-security-handle 'gnus-details "Quit.")
598 (mm-set-handle-multipart-parameter
599 mm-security-handle 'gnus-info "Quit.")
600 (setq info-is-set-p t)
601 nil))
602 (unless info-is-set-p
603 (mm-set-handle-multipart-parameter
604 mm-security-handle 'gnus-info "Failed"))
605 (throw 'error handle)))
606 (mm-set-handle-multipart-parameter
607 mm-security-handle 'gnus-info
608 (with-current-buffer mml2015-result-buffer
609 (mml2015-gpg-extract-signature-details))))
610 handle)))
611
612 (defun mml2015-gpg-clear-verify ()
613 (if (condition-case err
614 (prog1
615 (gpg-verify-cleartext (current-buffer) mml2015-result-buffer)
616 (mm-set-handle-multipart-parameter
617 mm-security-handle 'gnus-details
618 (with-current-buffer mml2015-result-buffer
619 (buffer-string))))
620 (error
621 (mm-set-handle-multipart-parameter
622 mm-security-handle 'gnus-details (mml2015-format-error err))
623 nil)
624 (quit
625 (mm-set-handle-multipart-parameter
626 mm-security-handle 'gnus-details "Quit.")
627 nil))
628 (mm-set-handle-multipart-parameter
629 mm-security-handle 'gnus-info
630 (with-current-buffer mml2015-result-buffer
631 (mml2015-gpg-extract-signature-details)))
632 (mm-set-handle-multipart-parameter
633 mm-security-handle 'gnus-info "Failed"))
634 (mml2015-extract-cleartext-signature))
635
636 (defun mml2015-gpg-sign (cont)
637 (let ((boundary (mml-compute-boundary cont))
638 (text (current-buffer)) signature)
639 (goto-char (point-max))
640 (unless (bolp)
641 (insert "\n"))
642 (with-temp-buffer
643 (unless (gpg-sign-detached text (setq signature (current-buffer))
644 mml2015-result-buffer
645 nil
646 (message-options-get 'message-sender)
647 t t) ; armor & textmode
648 (unless (> (point-max) (point-min))
649 (pop-to-buffer mml2015-result-buffer)
650 (error "Sign error")))
651 (goto-char (point-min))
652 (while (re-search-forward "\r+$" nil t)
653 (replace-match "" t t))
654 (set-buffer text)
655 (goto-char (point-min))
656 (insert (format "Content-Type: multipart/signed; boundary=\"%s\";\n"
657 boundary))
658 ;;; FIXME: what is the micalg?
659 (insert "\tmicalg=pgp-sha1; protocol=\"application/pgp-signature\"\n")
660 (insert (format "\n--%s\n" boundary))
661 (goto-char (point-max))
662 (insert (format "\n--%s\n" boundary))
663 (insert "Content-Type: application/pgp-signature\n\n")
664 (insert-buffer-substring signature)
665 (goto-char (point-max))
666 (insert (format "--%s--\n" boundary))
667 (goto-char (point-max)))))
668
669 (defun mml2015-gpg-encrypt (cont &optional sign)
670 (let ((boundary (mml-compute-boundary cont))
671 (text (current-buffer))
672 cipher)
673 (mm-with-unibyte-current-buffer
674 (with-temp-buffer
675 (mm-disable-multibyte)
676 ;; set up a function to call the correct gpg encrypt routine
677 ;; with the right arguments. (FIXME: this should be done
678 ;; differently.)
679 (flet ((gpg-encrypt-func
680 (sign plaintext ciphertext result recipients &optional
681 passphrase sign-with-key armor textmode)
682 (if sign
683 (gpg-sign-encrypt
684 plaintext ciphertext result recipients passphrase
685 sign-with-key armor textmode)
686 (gpg-encrypt
687 plaintext ciphertext result recipients passphrase
688 armor textmode))))
689 (unless (gpg-encrypt-func
690 sign ; passed in when using signencrypt
691 text (setq cipher (current-buffer))
692 mml2015-result-buffer
693 (split-string
694 (or
695 (message-options-get 'message-recipients)
696 (message-options-set 'message-recipients
697 (read-string "Recipients: ")))
698 "[ \f\t\n\r\v,]+")
699 nil
700 (message-options-get 'message-sender)
701 t t) ; armor & textmode
702 (unless (> (point-max) (point-min))
703 (pop-to-buffer mml2015-result-buffer)
704 (error "Encrypt error"))))
705 (goto-char (point-min))
706 (while (re-search-forward "\r+$" nil t)
707 (replace-match "" t t))
708 (set-buffer text)
709 (delete-region (point-min) (point-max))
710 (insert (format "Content-Type: multipart/encrypted; boundary=\"%s\";\n"
711 boundary))
712 (insert "\tprotocol=\"application/pgp-encrypted\"\n\n")
713 (insert (format "--%s\n" boundary))
714 (insert "Content-Type: application/pgp-encrypted\n\n")
715 (insert "Version: 1\n\n")
716 (insert (format "--%s\n" boundary))
717 (insert "Content-Type: application/octet-stream\n\n")
718 (insert-buffer-substring cipher)
719 (goto-char (point-max))
720 (insert (format "--%s--\n" boundary))
721 (goto-char (point-max))))))
722 489
723 ;;; pgg wrapper 490 ;;; pgg wrapper
724 491
725 (defvar pgg-default-user-id) 492 (defvar pgg-default-user-id)
726 (defvar pgg-errors-buffer) 493 (defvar pgg-errors-buffer)