(eval-when-compile (require 'epg)) (defvar epg-pgp50i-pgpv-program "pgpv") (defconst epg-pgp50i-message-alist '(("Message is encrypted." . "MESSAGE_IS_ENCRYPTED") ("Need a pass phrase to decrypt private key:" . "NEED_PASSPHRASE_TO_DECRYPT_KEY") ("Enter pass phrase: " . "ENTER_PASSPHRASE") ("Pass phrase is good." . "GOOD_PASSPHRASE") ("Cannot decrypt message. It can only be decrypted by:" . "CANNOT_DECRYPT"))) (defvar epg-pgp50i-status nil) (defun epg-pgp50i--start (context program args) (let ((args (append '("--headers" "--language=us" "--batchmode=0" "--force") (if (epg-context-armor context) '("--armor")) (if (epg-context-textmode context) '("--textmode")) (if (epg-context-output-file context) (list "-o" (epg-context-output-file context))) args)) (coding-system-for-write 'binary) process-connection-type (orig-mode (default-file-modes)) (buffer (generate-new-buffer " *epg*")) process) (if epg-debug (save-excursion (unless epg-debug-buffer (setq epg-debug-buffer (generate-new-buffer " *epg-debug*"))) (set-buffer epg-debug-buffer) (goto-char (point-max)) (insert (format "%s %s\n" program (mapconcat #'identity args " "))))) (with-current-buffer buffer (make-local-variable 'epg-read-point) (setq epg-read-point (point-min)) (make-local-variable 'epg-pending-status-list) (setq epg-pending-status-list nil) (make-local-variable 'epg-key-id) (setq epg-key-id nil) (make-local-variable 'epg-context) (setq epg-context context) (make-local-variable 'epg-pgp50i-status) (setq epg-pgp50i-status nil)) (unwind-protect (progn (set-default-file-modes 448) (setq process (apply #'start-process "epg" buffer program args))) (set-default-file-modes orig-mode)) (set-process-filter process #'epg-pgp50i--process-filter) (set-process-sentinel process #'ignore) (epg-context-set-process context process))) (defun epg-pgp50i--process-filter (process input) (if epg-debug (save-excursion (unless epg-debug-buffer (setq epg-debug-buffer (generate-new-buffer " *epg-debug*"))) (set-buffer epg-debug-buffer) (goto-char (point-max)) (insert input))) (if (buffer-live-p (process-buffer process)) (save-excursion (set-buffer (process-buffer process)) (goto-char (point-max)) (insert input) (unless epg-pgp50i-status (goto-char epg-read-point) (while (not (eobp)) (save-excursion (if (looking-at "\\(PRI\\|INF\\|QRY\\|STA\\|WRN\\|ERR\\): \\(.*\\)") (let ((message (match-string 2)) (pointer epg-pgp50i-message-alist) status symbol) (while pointer (if (string-match (car (car pointer)) message) (setq status (cdr (car pointer)) pointer nil)) (setq pointer (cdr pointer))) (when status (unless (looking-at ".*\n") (end-of-line) (insert "\n")) (if (member status epg-pending-status-list) (setq epg-pending-status-list nil)) (setq symbol (intern-soft (concat "epg-pgp50i--status-" status))) (if (and symbol (fboundp symbol)) (unwind-protect (progn (setq epg-pgp50i-status status) (funcall symbol epg-context message)) (setq epg-pgp50i-status nil))))))) (forward-line) (setq epg-read-point (point))))))) (defun epg-pgp50i--wait-for-line (context) (if (eq (process-status (epg-context-process context)) 'run) (save-excursion (set-buffer (process-buffer (epg-context-process context))) (goto-char epg-read-point) (beginning-of-line 2) (while (and (eq (process-status (epg-context-process context)) 'run) (not (if (looking-at ".*\n") (setq epg-read-point (point))))) (accept-process-output (epg-context-process context) 1)) (buffer-substring (point) (progn (end-of-line) (point)))))) (defun epg-pgp50i--status-ENTER_PASSPHRASE (context status) (epg--status-GET_HIDDEN context "passphrase.")) (defun epg-pgp50i--status-NEED_PASSPHRASE_TO_DECRYPT_KEY (context status) (let ((line (epg-pgp50i--wait-for-line context)) user-id entry) (when (and line (string-match "[ 0-9]+ bits, Key ID \\([0-9A-F]+\\)" line)) (setq epg-key-id (match-string 1 line) line (epg-pgp50i--wait-for-line context)) (when (and line (string-match "\"\\([^\"]+\\)\"" line)) (setq user-id (match-string 1 line) entry (assoc epg-key-id epg-user-id-alist)) (if entry (setcdr entry user-id) (setq epg-user-id-alist (cons (cons epg-key-id user-id) epg-user-id-alist))))))) (defadvice epg-start-decrypt (around epg-pgp50i activate) (if (eq (epg-context-protocol (ad-get-arg 0)) 'CMS) ad-do-it (unless (epg-data-file (ad-get-arg 1)) (error "Not a file")) (epg-context-set-operation context 'decrypt) (epg-context-set-result (ad-get-arg 0) nil) (epg-pgp50i--start context epg-pgp50i-pgpv-program (list (epg-data-file (ad-get-arg 1)))) (epg-wait-for-status (ad-get-arg 0) '("GOOD_PASSPHRASE")))) (defadvice epg-start-verify (around epg-pgp50i activate) (if (eq (epg-context-protocol (ad-get-arg 0)) 'CMS) ad-do-it (error "Not implemented yet"))) (defadvice epg-start-sign (around epg-pgp50i activate) (if (eq (epg-context-protocol (ad-get-arg 0)) 'CMS) ad-do-it (error "Not implemented yet"))) (defadvice epg-start-encrypt (around epg-pgp50i activate) (if (eq (epg-context-protocol (ad-get-arg 0)) 'CMS) ad-do-it (error "Not implemented yet"))) (provide 'epg-pgp50i) ;;; epg-pgp50i.el ends here