+ (with-current-buffer pgg-errors-buffer
+ (mml2015-gpg-extract-signature-details)))
+ (mm-set-handle-multipart-parameter
+ mm-security-handle 'gnus-info "Failed")))
+ (mml2015-extract-cleartext-signature))
+
+(defun mml2015-pgg-sign (cont)
+ (let ((pgg-errors-buffer mml2015-result-buffer)
+ (boundary (mml-compute-boundary cont))
+ (pgg-default-user-id (or (message-options-get 'mml-sender)
+ pgg-default-user-id))
+ (pgg-text-mode t)
+ entry)
+ (unless (pgg-sign-region (point-min) (point-max))
+ (pop-to-buffer mml2015-result-buffer)
+ (error "Sign error"))
+ (goto-char (point-min))
+ (insert (format "Content-Type: multipart/signed; boundary=\"%s\";\n"
+ boundary))
+ (if (setq entry (assq 2 (pgg-parse-armor
+ (with-current-buffer pgg-output-buffer
+ (buffer-string)))))
+ (setq entry (assq 'hash-algorithm (cdr entry))))
+ (insert (format "\tmicalg=%s; "
+ (if (cdr entry)
+ (downcase (format "pgp-%s" (cdr entry)))
+ "pgp-sha1")))
+ (insert "protocol=\"application/pgp-signature\"\n")
+ (insert (format "\n--%s\n" boundary))
+ (goto-char (point-max))
+ (insert (format "\n--%s\n" boundary))
+ (insert "Content-Type: application/pgp-signature\n\n")
+ (insert-buffer-substring pgg-output-buffer)
+ (goto-char (point-max))
+ (insert (format "--%s--\n" boundary))
+ (goto-char (point-max))))
+
+(defun mml2015-pgg-encrypt (cont &optional sign)
+ (let ((pgg-errors-buffer mml2015-result-buffer)
+ (pgg-text-mode t)
+ (boundary (mml-compute-boundary cont)))
+ (unless (pgg-encrypt-region (point-min) (point-max)
+ (split-string
+ (or
+ (message-options-get 'message-recipients)
+ (message-options-set 'message-recipients
+ (read-string "Recipients: ")))
+ "[ \f\t\n\r\v,]+")
+ sign)
+ (pop-to-buffer mml2015-result-buffer)
+ (error "Encrypt error"))
+ (delete-region (point-min) (point-max))
+ (goto-char (point-min))
+ (insert (format "Content-Type: multipart/encrypted; boundary=\"%s\";\n"
+ boundary))
+ (insert "\tprotocol=\"application/pgp-encrypted\"\n\n")
+ (insert (format "--%s\n" boundary))
+ (insert "Content-Type: application/pgp-encrypted\n\n")
+ (insert "Version: 1\n\n")
+ (insert (format "--%s\n" boundary))
+ (insert "Content-Type: application/octet-stream\n\n")
+ (insert-buffer-substring pgg-output-buffer)
+ (goto-char (point-max))
+ (insert (format "--%s--\n" boundary))
+ (goto-char (point-max))))
+
+;;; epg wrapper
+
+(defvar epg-user-id-alist)
+(defvar epg-digest-algorithm-alist)
+(defvar inhibit-redisplay)
+
+(autoload 'epg-make-context "epg")
+(autoload 'epg-context-set-armor "epg")
+(autoload 'epg-context-set-textmode "epg")
+(autoload 'epg-context-set-signers "epg")
+(autoload 'epg-context-result-for "epg")
+(autoload 'epg-new-signature-digest-algorithm "epg")
+(autoload 'epg-verify-result-to-string "epg")
+(autoload 'epg-list-keys "epg")
+(autoload 'epg-decrypt-string "epg")
+(autoload 'epg-verify-string "epg")
+(autoload 'epg-sign-string "epg")
+(autoload 'epg-encrypt-string "epg")
+(autoload 'epg-passphrase-callback-function "epg")
+(autoload 'epg-context-set-passphrase-callback "epg")
+(autoload 'epg-key-sub-key-list "epg")
+(autoload 'epg-sub-key-capability "epg")
+(autoload 'epg-sub-key-validity "epg")
+(autoload 'epg-configuration "epg-config")
+(autoload 'epg-expand-group "epg-config")
+(autoload 'epa-select-keys "epa")
+
+(defvar mml2015-epg-secret-key-id-list nil)
+
+(defun mml2015-epg-passphrase-callback (context key-id ignore)
+ (if (eq key-id 'SYM)
+ (epg-passphrase-callback-function context key-id nil)
+ (let* ((password-cache-key-id
+ (if (eq key-id 'PIN)
+ "PIN"
+ key-id))
+ entry
+ (passphrase
+ (password-read
+ (if (eq key-id 'PIN)
+ "Passphrase for PIN: "
+ (if (setq entry (assoc key-id epg-user-id-alist))
+ (format "Passphrase for %s %s: " key-id (cdr entry))
+ (format "Passphrase for %s: " key-id)))
+ password-cache-key-id)))
+ (when passphrase
+ (let ((password-cache-expiry mml2015-passphrase-cache-expiry))
+ (password-cache-add password-cache-key-id passphrase))
+ (setq mml2015-epg-secret-key-id-list
+ (cons password-cache-key-id mml2015-epg-secret-key-id-list))
+ (copy-sequence passphrase)))))