X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=mime-edit.el;h=d810941418a9e381e780d447299e9482afb1cfea;hb=93452613f785fcbf39de30c806711d718b284d41;hp=8538332bfb1b81f8447d109a7362af13f46c6d74;hpb=b67a99595b6fb3f2c5ca961261c8ff8b58646f7c;p=elisp%2Fsemi.git diff --git a/mime-edit.el b/mime-edit.el index 8538332..d810941 100644 --- a/mime-edit.el +++ b/mime-edit.el @@ -23,8 +23,8 @@ ;; 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: @@ -113,19 +113,7 @@ (require 'mime-view) (require 'signature) (require 'alist) -(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-buffer "smime" - "S/MIME encryption of current buffer.") -(autoload 'smime-sign-buffer "smime" - "S/MIME signature of current buffer.") +(require 'epa) ;;; @ version @@ -230,6 +218,9 @@ To insert a signature file automatically, call the function ("application" ("octet-stream" ("type" "" "tar" "shar")) ("postscript") + ("pdf") + ("msword") + ("vnd.ms-excel") ("vnd.ms-powerpoint") ("x-kiss" ("x-cnf"))) ("image" @@ -305,6 +296,10 @@ To insert a signature file automatically, call the function "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" @@ -316,7 +311,11 @@ To insert a signature file automatically, call the function "inline" (("filename" . file))) ("\\.ps$" "application" "postscript" nil - "quoted-printable" + "base64" + "attachment" (("filename" . file))) + ("\\.pdf$" + "application" "pdf" nil + "base64" "attachment" (("filename" . file))) ;; Pure binary @@ -608,8 +607,12 @@ If it is not specified for a major-mode, ") " (if (fboundp 'apel-version) (concat (apel-version) " ")) + "EasyPG/" epg-version-number " " (if (featurep 'xemacs) - (concat (cond ((featurep 'utf-2000) + (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" @@ -677,7 +680,7 @@ Tspecials means any character that matches with it in header must be quoted.") (concat "MIME-Version:" (mime-encode-field-body (concat " 1.0 (split by " mime-edit-version ")\n") - "MIME-Version:")) + "MIME-Version")) "MIME version field for message/partial.") @@ -732,6 +735,10 @@ Tspecials means any character that matches with it in header must be quoted.") (define-key mime-edit-mode-enclosure-map "\C-e" 'mime-edit-enclose-pgp-encrypted-region) (define-key mime-edit-mode-enclosure-map + "s" 'mime-edit-enclose-smime-signed-region) +(define-key mime-edit-mode-enclosure-map + "e" 'mime-edit-enclose-smime-encrypted-region) +(define-key mime-edit-mode-enclosure-map "\C-q" 'mime-edit-enclose-quote-region) (defvar mime-edit-mode-map (make-sparse-keymap) @@ -1642,6 +1649,13 @@ Parameter must be '(PROMPT CHOICE1 (CHOICE2...))." (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 @@ -1652,41 +1666,56 @@ Parameter must be '(PROMPT CHOICE1 (CHOICE2...))." (ctype (car ret)) (encoding (nth 1 ret)) (pgp-boundary (concat "pgp-sign-" boundary)) - micalg) + (context (epg-make-context)) + signature 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 (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-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))) - "")) + (epg-context-set-armor context t) + (epg-context-set-textmode context t) + (epg-context-set-signers + context + (epa-select-keys + context + "\ +Select keys for signing. +If no one is selected, default secret key is used. " + (if from + (list (nth 1 (std11-extract-address-components from)))) + t)) + (condition-case error + (setq signature + (epg-sign-string context + (buffer-substring (point-min) (point-max)) + 'detached)) + (error (signal 'mime-edit-error (cdr error)))) + (setq micalg (cdr (assq 'digest-algorithm + (car (epg-context-result-for context 'sign))))) (goto-char beg) (insert (format "--[[multipart/signed; boundary=\"%s\"%s; protocol=\"application/pgp-signature\"][7bit]] --%s -" pgp-boundary micalg pgp-boundary)) +" + pgp-boundary + (if micalg + (concat "; micalg=pgp-" + (downcase + (cdr (assq micalg + epg-digest-algorithm-alist)))) + "") + pgp-boundary)) (goto-char (point-max)) (insert (format "\n--%s Content-Type: application/pgp-signature Content-Transfer-Encoding: 7bit +Content-Description: OpenPGP Digital Signature " pgp-boundary)) - (insert-buffer-substring pgg-output-buffer) + (insert signature) (goto-char (point-max)) (insert (format "\n--%s--\n" pgp-boundary)))))) @@ -1722,17 +1751,18 @@ Content-Transfer-Encoding: 7bit (defun mime-edit-encrypt-pgp-mime (beg end boundary) (save-excursion (save-restriction - (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))) (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))) + (pgp-boundary (concat "pgp-" boundary)) + (context (epg-make-context)) + cipher) (goto-char beg) (insert header) (insert (format "Content-Type: %s\n" ctype)) @@ -1740,19 +1770,23 @@ Content-Transfer-Encoding: 7bit (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-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)) + (epg-context-set-armor context t) + (condition-case error + (setq cipher + (epg-encrypt-string + context + (buffer-substring (point-min) (point-max)) + (epa-select-keys + context + "\ +Select recipents for encryption. +If no one is selected, symmetric encryption will be performed. " + (mapcar (lambda (recipient) + (nth 1 (std11-extract-address-components + recipient))) + (split-string recipients + "\\([ \t\n]*,[ \t\n]*\\)+"))))) + (error (signal 'mime-edit-error (cdr error)))) (delete-region (point-min)(point-max)) (goto-char beg) (insert (format "--[[multipart/encrypted; @@ -1766,7 +1800,7 @@ Content-Type: application/octet-stream Content-Transfer-Encoding: 7bit " pgp-boundary pgp-boundary pgp-boundary)) - (insert-buffer-substring pgg-output-buffer) + (insert cipher) (goto-char (point-max)) (insert (format "\n--%s--\n" pgp-boundary))))))) @@ -1777,17 +1811,23 @@ Content-Transfer-Encoding: 7bit (let* ((ret (mime-edit-translate-region beg end boundary)) (ctype (car ret)) - (encoding (nth 1 ret))) + (encoding (nth 1 ret)) + (context (epg-make-context)) + signature) (goto-char beg) (insert (format "Content-Type: %s\n" ctype)) (if encoding (insert (format "Content-Transfer-Encoding: %s\n" encoding))) (insert "\n") - (or (pgg-sign-region beg (point-max) 'clearsign) - (throw 'mime-edit-error 'pgp-error)) + (condition-case error + (setq signature + (epg-sign-string context + (buffer-substring beg (point-max)) + 'clearsign)) + (error (signal 'mime-edit-error (cdr error)))) (goto-char beg) (insert - "--[[application/pgp; format=mime][7bit]]\n") + "--[[application/pgp; format=mime][7bit]]\n" signature) )))) (defun mime-edit-encrypt-pgp-kazu (beg end boundary) @@ -1801,75 +1841,150 @@ Content-Transfer-Encoding: 7bit (let* ((ret (mime-edit-translate-region beg end boundary)) (ctype (car ret)) - (encoding (nth 1 ret))) + (encoding (nth 1 ret)) + (context (epg-make-context)) + cipher) (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 (pgg-encrypt-region beg (point-max) recipients) - (throw 'mime-edit-error 'pgp-error)) + (epg-context-set-armor context t) + (condition-case error + (setq cipher + (epg-encrypt-string + context + (buffer-substring beg (point-max)) + (epa-select-keys + context + "\ +Select recipents for encryption. +If no one is selected, symmetric encryption will be performed. " + (mapcar (lambda (recipient) + (nth 1 (std11-extract-address-components + recipient))) + (split-string recipients + "\\([ \t\n]*,[ \t\n]*\\)+"))))) + (error (signal 'mime-edit-error (cdr error)))) (goto-char beg) (insert - "--[[application/pgp; format=mime][7bit]]\n") + "--[[application/pgp; format=mime][7bit]]\n" cipher) ))))) +(defun mime-edit-convert-lbt-string (string) + (let ((index 0)) + (while (setq index (string-match "\n" string index)) + (setq string (replace-match "\r\n" nil nil string) + index (+ index 2))) ;(length "\r\n") + string)) + (defun mime-edit-sign-smime (beg end boundary) (save-excursion (save-restriction - (let* ((ret (progn + (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)) - (smime-boundary (concat "smime-sign-" boundary))) + (smime-boundary (concat "smime-sign-" boundary)) + (context (epg-make-context 'CMS)) + signature micalg) (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 (smime-sign-buffer) - (throw 'mime-edit-error 'pgp-error))) + (epg-context-set-signers + context + (epa-select-keys + context + "\ +Select keys for signing. +If no one is selected, default secret key is used. " + (if from + (list (nth 1 (std11-extract-address-components from)))) + t)) + (condition-case error + (setq signature + (epg-sign-string context + (mime-edit-convert-lbt-string + (buffer-substring (point-min) (point-max))) + 'detached)) + (error (signal 'mime-edit-error (cdr error)))) + (setq micalg (cdr (assq 'digest-algorithm + (car (epg-context-result-for context 'sign))))) (goto-char beg) - (if (re-search-forward "^Content-Type:\\s-*" nil t) - (let* ((start (match-beginning 0)) - (body (buffer-substring (match-end 0) (std11-field-end)))) - (delete-region start (line-beginning-position 2)) - (goto-char beg) - (insert "--[[" body "][7bit]]\n"))))))) + (insert (format "--[[multipart/signed; + boundary=\"%s\"%s; + protocol=\"application/pkcs7-signature\"][7bit]] +--%s +" + smime-boundary + (if micalg + (concat "; micalg=" + (downcase + (cdr (assq micalg + epg-digest-algorithm-alist)))) + "") + 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 Digital Signature + +" smime-boundary) + (base64-encode-string signature)))))) (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-buffer) - (throw 'mime-edit-error 'pgp-error)) - (goto-char beg) - (if (re-search-forward "^Content-Type:\\s-*" nil t) - (let* ((start (match-beginning 0)) - (body (buffer-substring (match-end 0) (std11-field-end)))) - (delete-region start (line-beginning-position 2)) - (goto-char beg) - (insert "--[[" body "]]\n"))))))) + (let (recipients header) + (let ((ret (mime-edit-make-encrypt-recipient-header))) + (setq 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)) + (context (epg-make-context 'CMS)) + cipher) + (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) + (condition-case error + (setq cipher + (epg-encrypt-string + context + (buffer-substring (point-min) (point-max)) + (epa-select-keys + context + "\ +Select recipents for encryption. +If no one is selected, symmetric encryption will be performed. " + (mapcar (lambda (recipient) + (nth 1 (std11-extract-address-components + recipient))) + (split-string recipients + "\\([ \t\n]*,[ \t\n]*\\)+"))))) + (error (signal 'mime-edit-error (cdr error)))) + (delete-region (point-min)(point-max)) + (goto-char beg) + (insert (format "--[[application/pkcs7-mime; + smime-type=enveloped-data; + name=smime.p7m +Content-Disposition: attachment; filename=smime.p7m][base64]] + +") + (base64-encode-string cipher))))))) (defsubst replace-space-with-underline (str) (mapconcat (function @@ -2108,7 +2223,13 @@ Content-Transfer-Encoding: 7bit (narrow-to-region beg (mime-edit-content-end)) (goto-char beg) (while (re-search-forward "\\(\\=\\|[^\r]\\)\n" nil t) - (replace-match "\\1\r\n")))) + ;; 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")) @@ -2254,7 +2375,11 @@ and insert data encoded as ENCODING." (interactive "P") (mime-edit-insert-tag "application" "pgp-keys") (mime-edit-define-encoding "7bit") - (pgg-insert-key) + (let ((context (epg-make-context))) + (epg-context-set-armor context t) + (epg-export-keys-to-string context + (epa-select-keys context + "Select keys for export. "))) (if (and (not (eobp)) (not (looking-at mime-edit-single-part-tag-regexp))) (insert (mime-make-text-tag) "\n"))) @@ -2371,14 +2496,10 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n" (setq mime-edit-message-max-length (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" temporary-file-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*")) @@ -2464,6 +2585,7 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n" ;;; (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." @@ -2564,17 +2686,15 @@ Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n" (narrow-to-region beg end) (cond ((eq subtype 'pgp-encrypted) - (when (and - (progn + (when (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) + (insert (epg-decrypt-string + (epg-make-context) + (buffer-substring (match-beginning 0) + (point-max)))) + (delete-region (point)(point-max)) (mime-edit-decode-message-in-buffer nil not-decode-text) (delete-region (goto-char (point-min))