+(defun mime-mc-gpg-sign-region (start end &optional id unclear boundary)
+ (if (not (fboundp 'mc-gpg-insert-parser))
+ (load "mc-gpg")
+ )
+ (let ((buffer (get-buffer-create mc-buffer-name))
+ passwd args key
+ (parser (function mc-gpg-insert-parser))
+ (pgp-path mc-gpg-path)
+ micalg
+ (comment (mime-mc-comment))
+ )
+ (setq key (mc-gpg-lookup-key (or id mc-gpg-user-id)))
+ (setq passwd
+ (mc-activate-passwd
+ (cdr key)
+ (format "GnuPG passphrase for %s (%s): " (car key) (cdr key))))
+ (setq args (cons
+ (if boundary
+ "--detach-sign"
+ (if unclear
+ "--sign"
+ "--clearsign")
+ )
+ (list "--armor" "--batch" "--textmode" "--verbose"
+ "--local-user" (cdr key))
+ ))
+ (if boundary
+ (progn
+ (if (string-match "^pgp-" boundary)
+ (setq boundary
+ (concat "gpg-" (substring boundary (match-end 0))))
+ )
+ (if (not (or mime-mc-omit-micalg
+ (setq micalg
+ (cdr (assoc (cdr key) mime-mc-micalg-alist)))
+ ))
+ (with-temp-buffer
+ (message "Detecting the value of `micalg'...")
+ (insert "\n")
+ (if (let ((mc-passwd-timeout 60)) ;; Don't deactivate passwd.
+ (mime-mc-gpg-process-region
+ 1 2 passwd pgp-path
+ (list "--clearsign" "--armor" "--batch" "--textmode"
+ "--verbose" "--local-user" (cdr key))
+ parser buffer nil)
+ )
+ (progn
+ (std11-narrow-to-header)
+ (setq micalg
+ (downcase (or (std11-fetch-field "Hash") "md5"))
+ )
+ (set-alist 'mime-mc-micalg-alist (cdr key) micalg)
+ )
+ (or mc-passwd-timeout (mc-deactivate-passwd t))
+ ))
+ )))
+ (if (or mime-mc-omit-micalg micalg)
+ (progn
+ (message "Signing as %s ..." (car key))
+ (if (mime-mc-gpg-process-region
+ start end passwd pgp-path args parser buffer boundary comment)
+ (progn
+ (if boundary
+ (progn
+ (goto-char (point-min))
+ (insert
+ (format "\
+--[[multipart/signed; protocol=\"application/pgp-signature\";
+ boundary=\"%s\"%s][7bit]]\n"
+ boundary
+ (if mime-mc-omit-micalg
+ ""
+ (concat "; micalg=pgp-" micalg)
+ )
+ ))))
+ (message "Signing as %s ... Done." (car key))
+ t)
+ nil)
+ )
+ nil)))
+
+(defun mime-mc-gpg-encrypt-region (recipients start end &optional id sign)
+ (if (not (fboundp 'mc-gpg-encrypt-region))
+ (load "mc-gpg")
+ )
+ (let ((mc-pgp-always-sign (if (eq sign 'maybe)
+ mc-pgp-always-sign
+ 'never))
+ (comment (mime-mc-comment)))
+ (prog1
+ (mc-gpg-encrypt-region
+ (mc-split "\\([ \t\n]*,[ \t\n]*\\)+" recipients)
+ start end id nil)
+ (if comment
+ (mime-mc-replace-comment-field comment)
+ ))))
+
+
+;;; @ PGP 5.0i functions
+;;;
+
+(defun mime-mc-pgp50-process-region
+ (beg end passwd program args parser &optional buffer boundary comment)
+ "Similar to `mc-pgp50-process-region', however enclose an processed data
+with BOUNDARY if it is specified and replace the comment field with the
+optional argument COMMENT if it is specified."
+ (let ((obuf (current-buffer))
+ (process-connection-type nil)
+ (shell-file-name mime-mc-shell-file-name)
+ (shell-command-switch mime-mc-shell-command-switch)
+ mybuf result rgn proc results)
+ (if comment
+ (setq args (cons "+comment=DUMMY" args))
+ )
+ (unwind-protect
+ (catch ;; Returns non-nil if success, otherwise nil with error message.
+ 'mime-mc-pgp50-process-region-done
+
+ (setq mybuf (or buffer (generate-new-buffer " *mailcrypt temp")))
+ (set-buffer mybuf)
+ (erase-buffer)
+ (set-buffer obuf)
+ (buffer-disable-undo mybuf)
+ (setq proc
+ (apply 'start-process-shell-command "*PGP*" mybuf program
+ "2>&1" args))
+
+ ;; Now hand the process to the parser, which returns the exit
+ ;; status of the dead process and the limits of the region
+ ;; containing the PGP results.
+ (condition-case err
+ (setq results (funcall parser proc obuf beg end mybuf passwd))
+ (error
+ (message "%s" err)
+ (throw 'mime-mc-pgp50-process-region-done nil)
+ ))
+ (setq result (car results))
+ (setq rgn (cadr results))
+
+ ;; Hack to force a status_notify() in Emacs 19.29
+ (set-buffer mybuf)
+
+ ;; replace comment string
+ (if (and comment (consp rgn))
+ (setcdr rgn (mime-mc-replace-comment-field
+ comment (car rgn) (cdr rgn)))
+ )
+
+ ;; Hurm. FIXME; must get better result codes.
+ (if (stringp result)
+ (mc-message result))
+
+ ;; If the parser found something, migrate it to the old
+ ;; buffer. In particular, the parser's job is to return
+ ;; a cons of the form ( beg . end ) delimited the result
+ ;; of PGP in the new buffer.
+ (if (consp rgn)
+ (progn
+ (set-buffer obuf)
+ (if boundary
+ (save-restriction
+ (narrow-to-region beg end)
+ (goto-char beg)
+ (insert (format "--%s\n" boundary))
+ (goto-char (point-max))
+ (insert (format "\n--%s
+Content-Type: application/pgp-signature
+Content-Transfer-Encoding: 7bit
+
+" boundary))
+ (insert-buffer-substring mybuf (car rgn) (cdr rgn))
+ (goto-char (point-max))
+ (insert (format "\n--%s--\n" boundary))
+ )
+ (delete-region beg end)
+ (goto-char beg)
+ (insert-buffer-substring mybuf (car rgn) (cdr rgn))
+ )
+ (set-buffer mybuf)
+ (delete-region (car rgn) (cdr rgn))))
+
+ ;; Return nil on failure and exit code on success
+ (if rgn result nil))
+
+ ;; Cleanup even on nonlocal exit
+ (if (and proc (eq 'run (process-status proc)))
+ (interrupt-process proc))
+ (set-buffer obuf)
+ (or buffer (null mybuf) (kill-buffer mybuf))
+ rgn)))
+
+(defun mime-mc-pgp50-sign-parser (proc oldbuf start end newbuf passwd)
+ ;; This function is a copy of `mc-pgp50-sign-parser', however it is
+ ;; modified for parsing a detached sign.
+ (let (result results rgn)
+ ;; (setenv "PGPPASSFD" "0")
+ (set-buffer newbuf)
+ (goto-char (point-max))
+ (progn
+ (unwind-protect
+ (with-expect proc
+ (message "Sending passphrase...")
+ (expect-send (concat passwd "\n"))
+ (or mc-passwd-timeout (mc-deactivate-passwd t))
+ (expect "No files specified. Using stdin."
+ (message "Passphrase sent. Signing...")
+ (set-buffer oldbuf)
+ (process-send-region proc start end)
+ (set-buffer newbuf)
+ (process-send-eof proc)
+
+ ;; Test output of the program, looking for
+ ;; errors.
+ (expect-cond
+
+ ;; OPTION 1: Great! The data is now signed!
+ ("-----END PGP SIGNATURE-----"
+
+ ;; Catch the exit status.
+ (setq result (process-exit-status proc))
+ (delete-process proc)
+ (message "Signing complete.")
+
+ ;; Delete everything preceding the signed data.
+ (goto-char (point-max))
+ (re-search-backward
+ ;; "-----BEGIN PGP SIGNED MESSAGE-----" nil t)
+ "-----BEGIN PGP SIGNATURE-----" nil t)
+ (delete-region (point-min) (match-beginning 0))
+ (setq rgn (point-min))
+
+ ;; Convert out CR/NL -> NL
+ (goto-char (point-min))
+ (while (search-forward "\r\n" nil t)
+ (replace-match "\n"))
+
+ ;; Delete everything after the signature.
+ (goto-char (point-min))
+ (re-search-forward
+ "-----END PGP SIGNATURE-----\n" nil t)
+ (delete-region (match-end 0) (point-max))
+
+ ;; Return the exit status, with the region
+ ;; limits!
+ (setq rgn (cons rgn (point-max)))
+ (setq results (list result rgn)))
+
+
+ ;; OPTION 1.a: The data is now signed, but is 8bit data.
+ ("-----END PGP MESSAGE-----"
+
+ ;; Catch the exit status.
+ (setq result (process-exit-status proc))
+ (delete-process proc)
+ (message "Signing complete.")
+
+ ;; Delete everything preceding the signed data.
+ (goto-char (point-max))
+ (re-search-backward
+ "-----BEGIN PGP MESSAGE-----" nil t)
+ (delete-region (point-min) (match-beginning 0))
+ (setq rgn (point-min))
+
+ ;; Convert out CR/NL -> NL
+ (goto-char (point-min))
+ (while (search-forward "\r\n" nil t)
+ (replace-match "\n"))
+
+ ;; Delete everything after the signature.
+ (goto-char (point-min))
+ (re-search-forward
+ "-----END PGP MESSAGE-----\n" nil t)
+ (delete-region (match-end 0) (point-max))
+
+ ;; Return the exit status, with the region
+ ;; limits!
+ (setq rgn (cons rgn (point-max)))
+ (setq results (list result rgn)))
+
+
+ ;; OPTION 2: Awww...bad passphrase!
+ ("Enter pass phrase:"
+ (mc-deactivate-passwd t)
+ (interrupt-process proc)
+ (delete-process proc)
+
+ ;; Return the bad news.
+ (setq results '("Incorrect passphrase" nil)))
+
+ ;; OPTION 3: The program exits.
+ (exit
+ (setq results (list
+ (process-exit-status proc) nil)))))))
+ results)))
+
+(defun mime-mc-pgp50-sign-region (start end &optional id unclear boundary)
+ (if (not (fboundp 'mc-pgp50-sign-parser))
+ (load "mc-pgp5")
+ )
+ (let ((process-environment process-environment)
+ (buffer (get-buffer-create mc-buffer-name))
+ passwd args key
+ (parser (if boundary
+ (function mime-mc-pgp50-sign-parser)
+ (function mc-pgp50-sign-parser)))
+ (pgp-path mc-pgp50-pgps-path)
+ micalg
+ (comment (mime-mc-comment))
+ )
+ (setq key (mc-pgp50-lookup-key (or id mc-pgp50-user-id)))
+ (setq passwd
+ (mc-activate-passwd
+ (cdr key)
+ (format "PGP passphrase for %s (%s): " (car key) (cdr key))))
+ (setenv "PGPPASSFD" "0")
+ (setq args (if boundary
+ (list "-fbat" "+verbose=1" "+language=us" "+batchmode"
+ "-u" (cdr key))
+ (list "-fat" "+verbose=1" "+language=us"
+ (format "+clearsig=%s" (if unclear "off" "on"))
+ "+batchmode" "-u" (cdr key))
+ ))
+ (if (and boundary
+ (not (or mime-mc-omit-micalg
+ (setq micalg
+ (cdr (assoc (cdr key) mime-mc-micalg-alist)))
+ )))
+ (with-temp-buffer
+ (message "Detecting the value of `micalg'...")
+ (insert "\n")
+ (if (let ((mc-passwd-timeout 60)) ;; Don't deactivate passwd.
+ (mime-mc-pgp50-process-region
+ 1 2 passwd pgp-path
+ (list "-fat" "+verbose=1" "+language=us" "+clearsig=on"
+ "+batchmode" "-u" (cdr key))
+ (function mc-pgp50-sign-parser) buffer nil)
+ )
+ (progn
+ (std11-narrow-to-header)
+ (setq micalg (downcase (or (std11-fetch-field "Hash") "md5")))
+ (set-alist 'mime-mc-micalg-alist (cdr key) micalg)
+ )
+ (or mc-passwd-timeout (mc-deactivate-passwd t))
+ ))
+ )
+ (if (or mime-mc-omit-micalg micalg)
+ (progn
+ (message "Signing as %s ..." (car key))
+ (if (mime-mc-pgp50-process-region
+ start end passwd pgp-path args parser buffer boundary comment)
+ (progn
+ (if boundary
+ (progn
+ (goto-char (point-min))
+ (insert
+ (format "\
+--[[multipart/signed; protocol=\"application/pgp-signature\";
+ boundary=\"%s\"%s][7bit]]\n"
+ boundary
+ (if mime-mc-omit-micalg
+ ""
+ (concat "; micalg=pgp-" micalg)
+ )
+ ))))
+ (message "Signing as %s ... Done." (car key))
+ t)
+ nil)
+ )
+ nil)))
+
+(defun mime-mc-pgp50-encrypt-region (recipients start end &optional id sign)
+ (if (not (fboundp 'mc-pgp50-encrypt-region))
+ (load "mc-pgp5")
+ )
+ (let ((mc-pgp-always-sign (if (eq sign 'maybe)
+ mc-pgp-always-sign
+ 'never))
+ (comment (mime-mc-comment))
+ (mc-pgp50-comment "DUMMY"))
+ (prog1
+ (mc-pgp50-encrypt-region
+ (mc-split "\\([ \t\n]*,[ \t\n]*\\)+" recipients)
+ start end id nil)
+ (if comment
+ (mime-mc-replace-comment-field comment)
+ ))))
+
+
+;;; @ PGP 2.6 functions
+;;;
+