1 (eval-when-compile (require 'epg))
3 (defvar epg-pgp50i-pgpv-program "pgpv")
5 (defconst epg-pgp50i-message-alist
6 '(("Message is encrypted." .
7 "MESSAGE_IS_ENCRYPTED")
8 ("Need a pass phrase to decrypt private key:" .
9 "NEED_PASSPHRASE_TO_DECRYPT_KEY")
10 ("Enter pass phrase: " .
12 ("Pass phrase is good." .
14 ("Cannot decrypt message. It can only be decrypted by:" .
16 ("Good signature made .* by key:" .
18 ("BAD signature made .* by key:" .
20 ("Error .* checking signature: " .
22 ("Signature by unknown keyid: " .
23 "UNKNOWN_SIGNATURE")))
25 (defvar epg-pgp50i-status nil)
27 (defun epg-pgp50i--start (context program args)
28 (let ((args (append '("--headers" "--language=us")
29 (if (epg-context-armor context) '("--armor"))
30 (if (epg-context-textmode context) '("--textmode"))
31 (if (epg-context-output-file context)
32 (list "-o" (epg-context-output-file context)))
34 (coding-system-for-write 'binary)
35 process-connection-type
36 (orig-mode (default-file-modes))
37 (buffer (generate-new-buffer " *epg*"))
41 (unless epg-debug-buffer
42 (setq epg-debug-buffer (generate-new-buffer " *epg-debug*")))
43 (set-buffer epg-debug-buffer)
44 (goto-char (point-max))
45 (insert (format "%s %s\n"
47 (mapconcat #'identity args " ")))))
48 (with-current-buffer buffer
49 (make-local-variable 'epg-read-point)
50 (setq epg-read-point (point-min))
51 (make-local-variable 'epg-pending-status-list)
52 (setq epg-pending-status-list nil)
53 (make-local-variable 'epg-key-id)
55 (make-local-variable 'epg-context)
56 (setq epg-context context)
57 (make-local-variable 'epg-pgp50i-status)
58 (setq epg-pgp50i-status nil))
61 (set-default-file-modes 448)
63 (apply #'start-process "epg" buffer program args)))
64 (set-default-file-modes orig-mode))
65 (set-process-filter process #'epg-pgp50i--process-filter)
66 (set-process-sentinel process #'ignore)
67 (epg-context-set-process context process)))
69 (defun epg-pgp50i--process-filter (process input)
72 (unless epg-debug-buffer
73 (setq epg-debug-buffer (generate-new-buffer " *epg-debug*")))
74 (set-buffer epg-debug-buffer)
75 (goto-char (point-max))
77 (if (buffer-live-p (process-buffer process))
79 (set-buffer (process-buffer process))
80 (goto-char (point-max))
82 (unless epg-pgp50i-status
83 (goto-char epg-read-point)
87 "\\(PRI\\|INF\\|QRY\\|STA\\|WRN\\|ERR\\): \\(.*\\)")
88 (let ((message (match-string 2))
89 (pointer epg-pgp50i-message-alist)
92 (if (string-match (car (car pointer)) message)
93 (setq status (cdr (car pointer))
95 (setq pointer (cdr pointer)))
97 (unless (looking-at ".*\n")
100 (if (member status epg-pending-status-list)
101 (setq epg-pending-status-list nil))
102 (setq symbol (intern-soft (concat "epg-pgp50i--status-"
108 (setq epg-pgp50i-status status)
109 (funcall symbol epg-context message))
110 (setq epg-pgp50i-status nil)))))))
112 (setq epg-read-point (point)))))))
114 (defun epg-pgp50i--wait-for-line (context)
115 (if (eq (process-status (epg-context-process context)) 'run)
117 (set-buffer (process-buffer (epg-context-process context)))
118 (goto-char epg-read-point)
119 (beginning-of-line 2)
120 (while (and (eq (process-status (epg-context-process context)) 'run)
121 (not (if (looking-at ".*\n")
122 (setq epg-read-point (point)))))
123 (accept-process-output (epg-context-process context) 1))
124 (buffer-substring (point) (progn (end-of-line) (point))))))
126 (defun epg-pgp50i--status-ENTER_PASSPHRASE (context message)
127 (epg--status-GET_HIDDEN context "passphrase."))
129 (defun epg-pgp50i--read-key (context)
130 (let ((line (epg-pgp50i--wait-for-line context))
133 (string-match "[ 0-9]+ bits, Key ID \\([0-9A-F]+\\)" line))
134 (setq key-id (match-string 1 line))
135 (when (and (setq line (epg-pgp50i--wait-for-line context))
136 (string-match "\"\\([^\"]+\\)\"" line))
137 (setq user-id-list (cons (match-string 1 line) user-id-list)))
138 (cons key-id user-id-list))))
140 (defun epg-pgp50i--status-NEED_PASSPHRASE_TO_DECRYPT_KEY (context message)
141 (let* ((key (epg-pgp50i--read-key context))
142 (entry (assoc (car key) epg-user-id-alist)))
144 (setcdr entry (car (cdr key)))
145 (setq epg-user-id-alist (cons (cons (car key) (car (cdr key)))
147 (setq epg-key-id (car key))))
149 (defun epg-pgp50i--status-GOOD_SIGNATURE (context message)
150 (let ((key (epg-pgp50i--read-key context)))
151 (epg--status-*SIG context 'good (concat (car key) " " (car (cdr key))))))
153 (defadvice epg-start-decrypt
154 (around epg-pgp50i activate)
155 (if (eq (epg-context-protocol (ad-get-arg 0)) 'CMS)
157 (let ((context (ad-get-arg 0))
158 (cipher (ad-get-arg 1)))
159 (unless (epg-data-file cipher)
160 (error "Not a file"))
161 (epg-context-set-operation context 'decrypt)
162 (epg-context-set-result context nil)
163 (epg-pgp50i--start context epg-pgp50i-pgpv-program
164 (list "--batchmode=0" "--force"
165 (epg-data-file cipher))))))
167 (defadvice epg-start-verify
168 (around epg-pgp50i activate)
169 (if (eq (epg-context-protocol (ad-get-arg 0)) 'CMS)
171 (let ((context (ad-get-arg 0))
172 (signature (ad-get-arg 1))
173 (signed-text (ad-get-arg 2)))
174 (epg-context-set-operation context 'verify)
175 (epg-context-set-result context nil)
177 ;; Detached signature.
178 (if (epg-data-file signed-text)
179 (epg-pgp50i--start context
180 epg-pgp50i-pgpv-program
181 (list "--batchmode=1" "--force"
182 (epg-data-file signature)
183 (epg-data-file signed-text)))
184 (epg-pgp50i--start context
185 epg-pgp50i-pgpv-program
186 (list "--batchmode=1" "--force"
187 (epg-data-file signature)))
188 (if (eq (process-status (epg-context-process context)) 'run)
189 (process-send-string (epg-context-process context)
190 (epg-data-string signed-text)))
191 (if (eq (process-status (epg-context-process context)) 'run)
192 (process-send-eof (epg-context-process context))))
193 ;; Normal (or cleartext) signature.
194 (if (epg-data-file signature)
195 (epg-pgp50i--start context
196 epg-pgp50i-pgpv-program
197 (list "--batchmode=1" "--force"
198 (epg-data-file signature)))
199 (epg-pgp50i--start context
200 epg-pgp50i-pgpv-program
201 (list "--batchmode=1" "--force"))
202 (if (eq (process-status (epg-context-process context)) 'run)
203 (process-send-string (epg-context-process context)
204 (epg-data-string signature)))
205 (if (eq (process-status (epg-context-process context)) 'run)
206 (process-send-eof (epg-context-process context))))))))
208 (defadvice epg-start-sign
209 (around epg-pgp50i activate)
210 (if (eq (epg-context-protocol (ad-get-arg 0)) 'CMS)
212 (error "Not implemented yet")))
214 (defadvice epg-start-encrypt
215 (around epg-pgp50i activate)
216 (if (eq (epg-context-protocol (ad-get-arg 0)) 'CMS)
218 (error "Not implemented yet")))
220 (provide 'epg-pgp50i)
222 ;;; epg-pgp50i.el ends here