X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=epg-pgp50i.el;h=23416709e3cbeb7659e5d4679d580fdbb6ba1eba;hb=59b227deceb57a37a91af9cc4edcb5039f0c0b3b;hp=893e73e7df1ea4d1629fcb70423fa1342747b489;hpb=b2d3d75b3da5a0f97a31c4049660ecd6fd536641;p=elisp%2Fepg.git diff --git a/epg-pgp50i.el b/epg-pgp50i.el index 893e73e..2341670 100644 --- a/epg-pgp50i.el +++ b/epg-pgp50i.el @@ -12,12 +12,18 @@ ("Pass phrase is good." . "GOOD_PASSPHRASE") ("Cannot decrypt message. It can only be decrypted by:" . - "CANNOT_DECRYPT"))) - -(defvar epg-pgp50i-status nil) + "CANNOT_DECRYPT") + ("Good signature made .* by key:" . + "GOOD_SIGNATURE") + ("BAD signature made .* by key:" . + "BAD_SIGNATURE") + ("Error .* checking signature: " . + "ERROR_SIGNATURE") + ("Signature by unknown keyid: " . + "UNKNOWN_SIGNATURE"))) (defun epg-pgp50i--start (context program args) - (let ((args (append '("--headers" "--language=us" "--batchmode=0" "--force") + (let ((args (append '("--headers" "--language=us") (if (epg-context-armor context) '("--armor")) (if (epg-context-textmode context) '("--textmode")) (if (epg-context-output-file context) @@ -40,14 +46,14 @@ (with-current-buffer buffer (make-local-variable 'epg-read-point) (setq epg-read-point (point-min)) + (make-local-variable 'epg-process-filter-running) + (setq epg-process-filter-running nil) (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)) + (setq epg-context context)) (unwind-protect (progn (set-default-file-modes 448) @@ -71,85 +77,160 @@ (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) + (unless epg-process-filter-running + (unwind-protect + (progn + (setq epg-process-filter-running t) + (goto-char epg-read-point) + (while (not (eobp)) + (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)) + (funcall symbol epg-context message))))) + (forward-line) + (setq epg-read-point (point)))) + (setq epg-process-filter-running nil)))))) + +(defun epg-pgp50i--read-line (context) (if (eq (process-status (epg-context-process context)) 'run) (save-excursion (set-buffer (process-buffer (epg-context-process context))) + (forward-line) (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) + (if (looking-at ".*\n") + (buffer-substring (point) (progn (end-of-line) (point))))))) + +(defun epg-pgp50i--status-ENTER_PASSPHRASE (context message) (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) +(defun epg-pgp50i--read-key (context) + (let ((line (epg-pgp50i--read-line context)) + key-id user-id-list) (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))))))) + (setq key-id (match-string 1 line)) + (while (and (setq line (epg-pgp50i--read-line context)) + (string-match "\"\\([^\"]+\\)\"" line)) + (setq user-id-list (cons (match-string 1 line) user-id-list))) + (cons key-id user-id-list)))) + +(defun epg-pgp50i--status-NEED_PASSPHRASE_TO_DECRYPT_KEY (context message) + (let* ((key (epg-pgp50i--read-key context)) + (entry (assoc (car key) epg-user-id-alist))) + (if entry + (setcdr entry (car (cdr key))) + (setq epg-user-id-alist (cons (cons (car key) (car (cdr key))) + epg-user-id-alist))) + (setq epg-key-id (car key)))) + +(defun epg-pgp50i--status-CANNOT_DECRYPT (context message) + (epg-context-set-result-for + context 'error + (cons (cons 'decryption-failed + (epg-pgp50i--read-key context)) + (epg-context-result-for context 'error)))) + +(defun epg-pgp50i--parse-time (string) + (if (string-match "\\`\\([0-9]+\\)-\\([0-9]+\\)-\\([0-9]+\\) \ +\\([0-9][0-9]\\):\\([0-9][0-9]\\) GMT\\'" string) + (encode-time 0 + (string-to-number (match-string 5 string)) + (string-to-number (match-string 4 string)) + (string-to-number (match-string 3 string)) + (string-to-number (match-string 2 string)) + (string-to-number (match-string 1 string)) + 0))) + +(defun epg-pgp50i--status-GOOD_SIGNATURE (context message) + (if (string-match "Good signature made \\(.*\\) by key:" message) + (let ((time (epg-pgp50i--parse-time (match-string 1 message))) + (key (epg-pgp50i--read-key context))) + (epg--status-*SIG context 'good (concat (car key) " " (car (cdr key)))) + (epg-signature-set-creation-time + (car (epg-context-result-for context 'verify)) + time)))) + +(defun epg-pgp50i--status-BAD_SIGNATURE (context message) + (if (string-match "BAD signature made \\(.*\\) by key:" message) + (let ((time (epg-pgp50i--parse-time (match-string 1 message))) + (key (epg-pgp50i--read-key context))) + (epg--status-*SIG context 'good (concat (car key) " " (car (cdr key)))) + (epg-signature-set-creation-time + (car (epg-context-result-for context 'verify)) + time)))) (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)))))) + (let ((context (ad-get-arg 0)) + (cipher (ad-get-arg 1))) + (unless (epg-data-file cipher) + (error "Not a file")) + (epg-context-set-operation context 'decrypt) + (epg-context-set-result context nil) + (epg-pgp50i--start context epg-pgp50i-pgpv-program + (list "--batchmode=0" "--force" + (epg-data-file cipher)))))) (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"))) + (let ((context (ad-get-arg 0)) + (signature (ad-get-arg 1)) + (signed-text (ad-get-arg 2))) + (epg-context-set-operation context 'verify) + (epg-context-set-result context nil) + (if signed-text + ;; Detached signature. + (if (epg-data-file signed-text) + (epg-pgp50i--start context + epg-pgp50i-pgpv-program + (list "--batchmode=1" "--force" + (epg-data-file signature) + (epg-data-file signed-text))) + (epg-pgp50i--start context + epg-pgp50i-pgpv-program + (list "--batchmode=1" "--force" + (epg-data-file signature))) + (if (eq (process-status (epg-context-process context)) 'run) + (process-send-string (epg-context-process context) + (epg-data-string signed-text))) + (if (eq (process-status (epg-context-process context)) 'run) + (process-send-eof (epg-context-process context)))) + ;; Normal (or cleartext) signature. + (if (epg-data-file signature) + (epg-pgp50i--start context + epg-pgp50i-pgpv-program + (list "--batchmode=1" "--force" + (epg-data-file signature))) + (epg-pgp50i--start context + epg-pgp50i-pgpv-program + (list "--batchmode=1" "--force")) + (if (eq (process-status (epg-context-process context)) 'run) + (process-send-string (epg-context-process context) + (epg-data-string signature))) + (if (eq (process-status (epg-context-process context)) 'run) + (process-send-eof (epg-context-process context)))))))) (defadvice epg-start-sign (around epg-pgp50i activate)