da830fd4e43f0075d314e0c7acdac067e02c9fe6
[elisp/epg.git] / epg.el
1 ;;; epg.el --- EasyPG, yet another GnuPG interface.
2 ;; Copyright (C) 1999, 2000, 2002, 2003, 2004,
3 ;;   2005, 2006 Free Software Foundation, Inc.
4 ;; Copyright (C) 2006 Daiki Ueno
5
6 ;; Author: Daiki Ueno <ueno@unixuser.org>
7 ;; Keywords: PGP, GnuPG
8
9 ;; This file is part of EasyPG.
10
11 ;; This program is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
14 ;; any later version.
15
16 ;; This program is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 ;; GNU General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
23 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 ;; Boston, MA 02110-1301, USA.
25
26 ;;; Code:
27
28 (defgroup epg ()
29   "EasyPG, yet another GnuPG interface.")
30
31 (defcustom epg-gpg-program "gpg"
32   "The `gpg' executable."
33   :group 'epg
34   :type 'string)
35
36 (defvar epg-user-id nil
37   "GnuPG ID of your default identity.")
38
39 (defvar epg-user-id-alist nil
40   "An alist mapping from key ID to user ID.")
41
42 (defvar epg-read-point nil)
43 (defvar epg-pending-status-list nil)
44 (defvar epg-key-id nil)
45 (defvar epg-context nil)
46 (defvar epg-debug nil)
47
48 (defvar epg-colons-pub-spec
49   '((trust "[^:]")
50     (length "[0-9]+" 0 string-to-number)
51     (algorithm "[0-9]+" 0 string-to-number)
52     (key-id "[^:]+")
53     (creation-date "[0-9]+")
54     (expiration-date "[0-9]+")
55     nil
56     (ownertrust "[^:]")
57     nil
58     nil
59     (capability "[escaESCA]*"))
60   "The schema of keylisting output whose type is \"pub\".
61 This is used by `epg-list-keys'.")
62
63 (defvar epg-colons-sec-spec
64   '((trust "[^:]")
65     (length "[0-9]+" 0 string-to-number)
66     (algorithm "[0-9]+" 0 string-to-number)
67     (key-id "[^:]+")
68     (creation-date "[0-9]+")
69     (expiration-date "[0-9]+")
70     nil
71     (ownertrust "[^:]"))
72 "The schema of keylisting output whose type is \"sec\".
73 This is used by `epg-list-keys'.")
74
75 (defvar epg-colons-uid-spec
76   '((trust "[^:]")
77     nil
78     nil
79     nil
80     (creation-date "[0-9]+")
81     (expiration-date "[0-9]+")
82     (hash "[^:]+")
83     nil
84     (user-id "[^:]+"))
85   "The schema of keylisting output whose type is \"uid\".
86 This is used by `epg-list-keys'.")
87     
88 (defun epg-make-context (&optional protocol armor textmode include-certs)
89   "Return a context object."
90   (vector protocol armor textmode include-certs
91           (cons #'epg-passphrase-callback-function nil)
92           (cons #'epg-progress-callback-function nil)
93           nil nil nil nil))
94
95 (defun epg-context-protocol (context)
96   "Return the protocol used within the context."
97   (aref context 0))
98
99 (defun epg-context-armor (context)
100   "Return t if the output shouled be ASCII armored in the CONTEXT context."
101   (aref context 1))
102
103 (defun epg-context-textmode (context)
104   "Return t if canonical text mode should be used in the CONTEXT context."
105   (aref context 2))
106
107 (defun epg-context-include-certs (context)
108   "Return how many certificates should be included in an S/MIME signed
109 message."
110   (aref context 3))
111
112 (defun epg-context-passphrase-callback-info (context)
113   "Return the function used to query passphrase."
114   (aref context 4))
115
116 (defun epg-context-progress-callback-info (context)
117   "Return the function which handles progress update."
118   (aref context 5))
119
120 (defun epg-context-signers (context)
121   "Return the list of key-id for singning."
122   (aref context 6))
123
124 (defun epg-context-process (context)
125   "Return the process object of `epg-gpg-program'.
126 This function is for internal use only."
127   (aref context 7))
128
129 (defun epg-context-output-file (context)
130   "Return the output file of `epg-gpg-program'.
131 This function is for internal use only."
132   (aref context 8))
133
134 (defun epg-context-result (context)
135   "Return the result of the previous cryptographic operation."
136   (aref context 9))
137
138 (defun epg-context-set-protocol (context protocol)
139   "Set the protocol used within the context."
140   (aset context 0 protocol))
141
142 (defun epg-context-set-armor (context armor)
143   "Specify if the output shouled be ASCII armored in the CONTEXT context."
144   (aset context 1 armor))
145
146 (defun epg-context-set-textmode (context textmode)
147   "Specify if canonical text mode should be used in the CONTEXT context."
148   (aset context 2 textmode))
149
150 (defun epg-context-set-include-certs (context include-certs)
151  "Set how many certificates should be included in an S/MIME signed message."
152   (aset context 3 include-certs))
153
154 (defun epg-context-set-passphrase-callback-info (context
155                                                  passphrase-callback-info)
156   "Set the function used to query passphrase."
157   (aset context 4 passphrase-callback-info))
158
159 (defun epg-context-set-progress-callback-info (context progress-callback-info)
160   "Set the function which handles progress update."
161   (aset context 5 progress-callback-info))
162
163 (defun epg-context-set-signers (context signers)
164  "Set the list of key-id for singning."
165   (aset context 6 signers))
166
167 (defun epg-context-set-process (context process)
168   "Set the process object of `epg-gpg-program'.
169 This function is for internal use only."
170   (aset context 7 process))
171
172 (defun epg-context-set-output-file (context output-file)
173   "Set the output file of `epg-gpg-program'.
174 This function is for internal use only."
175   (aset context 8 output-file))
176
177 (defun epg-context-set-result (context result)
178   "Set the result of the previous cryptographic operation."
179   (aset context 9 result))
180
181 (defun epg-make-signature (status key-id user-id)
182   "Return a signature object."
183   (vector status key-id user-id nil nil))
184
185 (defun epg-signature-status (signature)
186   "Return the status code of SIGNATURE."
187   (aref signature 0))
188
189 (defun epg-signature-key-id (signature)
190   "Return the key-id of SIGNATURE."
191   (aref signature 1))
192
193 (defun epg-signature-user-id (signature)
194   "Return the user-id of SIGNATURE."
195   (aref signature 2))
196   
197 (defun epg-signature-validity (signature)
198   "Return the validity of SIGNATURE."
199   (aref signature 3))
200
201 (defun epg-signature-fingerprint (signature)
202   "Return the fingerprint of SIGNATURE."
203   (aref signature 4))
204
205 (defun epg-signature-set-status (signature status)
206  "Set the status code of SIGNATURE."
207   (aset signature 0 status))
208
209 (defun epg-signature-set-key-id (signature key-id)
210  "Set the key-id of SIGNATURE."
211   (aset signature 1 key-id))
212
213 (defun epg-signature-set-user-id (signature user-id)
214  "Set the user-id of SIGNATURE."
215   (aset signature 2 user-id))
216   
217 (defun epg-signature-set-validity (signature validity)
218  "Set the validity of SIGNATURE."
219   (aset signature 3 validity))
220
221 (defun epg-signature-set-fingerprint (signature fingerprint)
222  "Set the fingerprint of SIGNATURE."
223   (aset signature 4 fingerprint))
224
225 (defun epg-context-result-for (context name)
226   (cdr (assq name (epg-context-result context))))
227
228 (defun epg-context-set-result-for (context name value)
229   (let* ((result (epg-context-result context))
230          (entry (assq name result)))
231     (if entry
232         (setcdr entry value)
233       (epg-context-set-result context (cons (cons name value) result)))))
234
235 (defun epg-start (context args)
236   "Start `epg-gpg-program' in a subprocess with given ARGS."
237   (let* ((args (append (list "--no-tty"
238                              "--status-fd" "1"
239                              "--command-fd" "0"
240                              "--yes") ; overwrite
241                        (if (epg-context-armor context) '("--armor"))
242                        (if (epg-context-textmode context) '("--textmode"))
243                        (if (epg-context-output-file context)
244                            (list "--output" (epg-context-output-file context)))
245                        args))
246          (coding-system-for-write 'binary)
247          process-connection-type
248          (orig-mode (default-file-modes))
249          (buffer (generate-new-buffer " *epg*"))
250          process)
251     (with-current-buffer buffer
252       (make-local-variable 'epg-read-point)
253       (setq epg-read-point (point-min))
254       (make-local-variable 'epg-pending-status-list)
255       (setq epg-pending-status-list nil)
256       (make-local-variable 'epg-key-id)
257       (setq epg-key-id nil)
258       (make-local-variable 'epg-context)
259       (setq epg-context context))
260     (unwind-protect
261         (progn
262           (set-default-file-modes 448)
263           (setq process
264                 (apply #'start-process "epg" buffer epg-gpg-program args)))
265       (set-default-file-modes orig-mode))
266     (set-process-filter process #'epg-process-filter)
267     (epg-context-set-process context process)))
268
269 (defun epg-process-filter (process input)
270   (if epg-debug
271       (save-excursion
272         (set-buffer (get-buffer-create  " *epg-debug*"))
273         (goto-char (point-max))
274         (insert input)))
275   (if (buffer-live-p (process-buffer process))
276       (save-excursion
277         (set-buffer (process-buffer process))
278         (goto-char (point-max))
279         (insert input)
280         (goto-char epg-read-point)
281         (beginning-of-line)
282         (while (looking-at ".*\n")      ;the input line is finished
283           (save-excursion
284             (if (looking-at "\\[GNUPG:] \\([A-Z_]+\\) ?\\(.*\\)")
285                 (let* ((status (match-string 1))
286                        (string (match-string 2))
287                        (symbol (intern-soft (concat "epg-status-" status))))
288                   (if (member status epg-pending-status-list)
289                       (setq epg-pending-status-list nil))
290                   (if (and symbol
291                            (fboundp symbol))
292                       (funcall symbol process string)))))
293           (forward-line))
294         (setq epg-read-point (point)))))
295
296 (defun epg-read-output (context)
297   (with-temp-buffer
298     (if (fboundp 'set-buffer-multibyte)
299         (set-buffer-multibyte nil))
300     (if (file-exists-p (epg-context-output-file context))
301         (let ((coding-system-for-read (if (epg-context-textmode context)
302                                           'raw-text
303                                         'binary)))
304           (insert-file-contents (epg-context-output-file context))
305           (buffer-string)))))
306
307 (defun epg-wait-for-status (context status-list)
308   (with-current-buffer (process-buffer (epg-context-process context))
309     (setq epg-pending-status-list status-list)
310     (while (and (eq (process-status (epg-context-process context)) 'run)
311                 epg-pending-status-list)
312       (accept-process-output (epg-context-process context) 1))))
313
314 (defun epg-wait-for-completion (context)
315   (if (eq (process-status (epg-context-process context)) 'run)
316       (process-send-eof (epg-context-process context)))
317   (while (eq (process-status (epg-context-process context)) 'run)
318     ;; We can't use accept-process-output instead of sit-for here
319     ;; because it may cause an interrupt during the sentinel execution.
320     (sit-for 0.1)))
321
322 (defun epg-reset (context)
323   (if (and (epg-context-process context)
324            (buffer-live-p (process-buffer (epg-context-process context))))
325       (kill-buffer (process-buffer (epg-context-process context))))
326   (epg-context-set-process context nil)
327   (if (file-exists-p (epg-context-output-file context))
328       (delete-file (epg-context-output-file context))))
329
330 (defun epg-status-USERID_HINT (process string)
331   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
332       (let* ((key-id (match-string 1 string))
333              (user-id (match-string 2 string))
334              (entry (assoc key-id epg-user-id-alist)))
335         (if entry
336             (setcdr entry user-id)
337           (setq epg-user-id-alist (cons (cons key-id user-id)
338                                         epg-user-id-alist))))))
339
340 (defun epg-status-NEED_PASSPHRASE (process string)
341   (if (string-match "\\`\\([^ ]+\\)" string)
342       (setq epg-key-id (match-string 1 string))))
343
344 (defun epg-status-NEED_PASSPHRASE_SYM (process string)
345   (setq epg-key-id 'SYM))
346
347 (defun epg-status-NEED_PASSPHRASE_PIN (process string)
348   (setq epg-key-id 'PIN))
349
350 (defun epg-status-GET_HIDDEN (process string)
351   (let ((passphrase
352          (funcall (car (epg-context-passphrase-callback-info epg-context))
353                   epg-key-id
354                   (cdr (epg-context-passphrase-callback-info epg-context))))
355         string)
356     (if passphrase
357         (unwind-protect
358             (progn
359               (setq string (concat passphrase "\n"))
360               (fillarray passphrase 0)
361               (setq passphrase nil)
362               (process-send-string process string))
363           (if string
364               (fillarray string 0))))))
365
366 (defun epg-status-GOODSIG (process string)
367   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
368       (epg-context-set-result-for
369        epg-context
370        'verify
371        (cons (epg-make-signature 'good
372                                  (match-string 1 string)
373                                  (match-string 2 string))
374              (epg-context-result-for epg-context 'verify)))))
375
376 (defun epg-status-EXPSIG (process string)
377   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
378       (epg-context-set-result-for
379        epg-context
380        'verify
381        (cons (epg-make-signature 'expired
382                                  (match-string 1 string)
383                                  (match-string 2 string))
384              (epg-context-result-for epg-context 'verify)))))
385
386 (defun epg-status-EXPKEYSIG (process string)
387   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
388       (epg-context-set-result-for
389        epg-context
390        'verify
391        (cons (epg-make-signature 'expired-key
392                                  (match-string 1 string)
393                                  (match-string 2 string))
394              (epg-context-result-for epg-context 'verify)))))
395
396 (defun epg-status-REVKEYSIG (process string)
397   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
398       (epg-context-set-result-for
399        epg-context
400        'verify
401        (cons (epg-make-signature 'revoked-key
402                                  (match-string 1 string)
403                                  (match-string 2 string))
404              (epg-context-result-for epg-context 'verify)))))
405
406 (defun epg-status-BADSIG (process string)
407   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
408       (epg-context-set-result-for
409        epg-context
410        'verify
411        (cons (epg-make-signature 'bad
412                                  (match-string 1 string)
413                                  (match-string 2 string))
414              (epg-context-result-for epg-context 'verify)))))
415
416 (defun epg-status-VALIDSIG (process string)
417   (let ((signature (car (epg-context-result-for epg-context 'verify))))
418     (if (and signature
419              (eq (epg-signature-status signature) 'good)
420              (string-match "\\`\\([^ ]+\\) " string))
421         (epg-signature-set-fingerprint signature (match-string 1 string)))))
422
423 (defun epg-status-TRUST_UNDEFINED (process string)
424   (let ((signature (car (epg-context-result-for epg-context 'verify))))
425     (if (and signature
426              (eq (epg-signature-status signature) 'good))
427         (epg-signature-set-validity signature 'undefined))))
428
429 (defun epg-status-TRUST_NEVER (process string)
430   (let ((signature (car (epg-context-result-for epg-context 'verify))))
431     (if (and signature
432              (eq (epg-signature-status signature) 'good))
433         (epg-signature-set-validity signature 'never))))
434
435 (defun epg-status-TRUST_MARGINAL (process string)
436   (let ((signature (car (epg-context-result-for epg-context 'verify))))
437     (if (and signature
438              (eq (epg-signature-status signature) 'marginal))
439         (epg-signature-set-validity signature 'marginal))))
440
441 (defun epg-status-TRUST_FULLY (process string)
442   (let ((signature (car (epg-context-result-for epg-context 'verify))))
443     (if (and signature
444              (eq (epg-signature-status signature) 'good))
445         (epg-signature-set-validity signature 'fully))))
446
447 (defun epg-status-TRUST_ULTIMATE (process string)
448   (let ((signature (car (epg-context-result-for epg-context 'verify))))
449     (if (and signature
450              (eq (epg-signature-status signature) 'good))
451         (epg-signature-set-validity signature 'ultimate))))
452
453 (defun epg-status-PROGRESS (process string)
454   (if (string-match "\\`\\([^ ]+\\) \\([^ ]\\) \\([0-9]+\\) \\([0-9]+\\)"
455                     string)
456       (funcall (car (epg-context-progress-callback-info epg-context))
457                (match-string 1 string)
458                (match-string 2 string)
459                (string-to-number (match-string 3 string))
460                (string-to-number (match-string 4 string))
461                (cdr (epg-context-progress-callback-info epg-context)))))
462
463 (defun epg-status-DECRYPTION_FAILED (process string)
464   (epg-context-set-result-for
465    epg-context 'error
466    (cons 'decryption-failed
467          (epg-context-result-for epg-context 'error))))
468
469 (defun epg-status-NODATA (process string)
470   (epg-context-set-result-for
471    epg-context 'error
472    (cons (cons 'no-data (string-to-number string))
473          (epg-context-result-for epg-context 'error))))
474
475 (defun epg-status-UNEXPECTED (process string)
476   (epg-context-set-result-for
477    epg-context 'error
478    (cons (cons 'unexpected (string-to-number string))
479          (epg-context-result-for epg-context 'error))))
480
481 (defun epg-status-KEYEXPIRED (process string)
482   (epg-context-set-result-for
483    epg-context 'error
484    (cons (cons 'key-expired string)
485          (epg-context-result-for epg-context 'error))))
486
487 (defun epg-status-KEYREVOKED (process string)
488   (epg-context-set-result-for
489    epg-context 'error
490    (cons 'key-revoked
491          (epg-context-result-for epg-context 'error))))
492
493 (defun epg-status-BADARMOR (process string)
494   (epg-context-set-result-for
495    epg-context 'error
496    (cons 'bad-armor
497          (epg-context-result-for epg-context 'error))))
498
499 (defun epg-passphrase-callback-function (key-id handback)
500   (read-passwd
501    (if (eq key-id 'SYM)
502        "Passphrase for symmetric encryption: "
503      (if (eq key-id 'PIN)
504          "Passphrase for PIN: "
505        (let ((entry (assoc key-id epg-user-id-alist)))
506          (if entry
507              (format "Passphrase for %s %s: " key-id (cdr entry))
508            (format "Passphrase for %s: " key-id)))))))
509
510 (defun epg-progress-callback-function (what char current total handback)
511   (message "%s: %d%%/%d%%" what current total))
512
513 (defun epg-list-keys (name &optional secret)
514   "List keys associated with STRING."
515   (let ((args (list "--with-colons" "--no-greeting" "--batch"
516                     "--fixed-list-mode"
517                     (if secret "--list-secret-keys" "--list-keys")
518                     name))
519         keys type symbol pointer)
520     (with-temp-buffer
521       (apply #'call-process epg-gpg-program nil (list t nil) nil args)
522       (goto-char (point-min))
523       (while (looking-at "\\([a-z][a-z][a-z]\\):\\(.*\\)")
524         (setq type (match-string 1)
525               symbol (intern-soft (format "epg-colons-%s-spec" type)))
526         (if (member type '("pub" "sec"))
527             (setq keys (cons nil keys)))
528         (if (and symbol
529                  (boundp symbol))
530             (setcar keys (cons (cons (intern type)
531                                      (epg-parse-colons
532                                       (symbol-value symbol)
533                                       (match-string 2)))
534                                (car keys))))
535         (forward-line)))
536     (setq pointer keys)
537     (while pointer
538       (setcar pointer (nreverse (car pointer)))
539       (setq pointer (cdr pointer)))
540     (nreverse keys)))
541
542 (defun epg-parse-colons (alist string)
543   (let ((index 0)
544         result)
545     (while (and alist
546                 (or (null (car alist))
547                     (eq index
548                         (string-match
549                          (concat "\\(" (nth 1 (car alist)) "\\)?:")
550                          string index))))
551       (if (car alist)
552           (progn
553             (setq index (match-end 0))
554             (if (match-beginning 1)
555                 (setq result
556                       (cons (cons (car (car alist))
557                                   (funcall (or (nth 3 (car alist)) #'identity)
558                                            (match-string
559                                             (1+ (or (nth 2 (car alist)) 0))
560                                             string)))
561                             result))))
562         (setq index (1+ index)))
563       (setq alist (cdr alist)))
564     (nreverse result)))
565
566 (if (fboundp 'make-temp-file)
567     (defalias 'epg-make-temp-file 'make-temp-file)
568   ;; stolen from poe.el.
569   (defun epg-make-temp-file (prefix)
570     "Create a temporary file.
571 The returned file name (created by appending some random characters at the end
572 of PREFIX, and expanding against `temporary-file-directory' if necessary),
573 is guaranteed to point to a newly created empty file.
574 You can then use `write-region' to write new data into the file."
575     (let (tempdir tempfile)
576       (unwind-protect
577           (let (file)
578             ;; First, create a temporary directory.
579             (while (condition-case ()
580                        (progn
581                          (setq tempdir (make-temp-name
582                                         (concat
583                                          (file-name-directory prefix)
584                                          "DIR")))
585                          ;; return nil or signal an error.
586                          (make-directory tempdir))
587                      ;; let's try again.
588                      (file-already-exists t)))
589             (set-file-modes tempdir 448)
590             ;; Second, create a temporary file in the tempdir.
591             ;; There *is* a race condition between `make-temp-name'
592             ;; and `write-region', but we don't care it since we are
593             ;; in a private directory now.
594             (setq tempfile (make-temp-name (concat tempdir "/EMU")))
595             (write-region "" nil tempfile nil 'silent)
596             (set-file-modes tempfile 384)
597             ;; Finally, make a hard-link from the tempfile.
598             (while (condition-case ()
599                        (progn
600                          (setq file (make-temp-name prefix))
601                          ;; return nil or signal an error.
602                          (add-name-to-file tempfile file))
603                      ;; let's try again.
604                      (file-already-exists t)))
605             file)
606         ;; Cleanup the tempfile.
607         (and tempfile
608              (file-exists-p tempfile)
609              (delete-file tempfile))
610         ;; Cleanup the tempdir.
611         (and tempdir
612              (file-directory-p tempdir)
613              (delete-directory tempdir))))))
614
615 ;;;###autoload
616 (defun epg-start-decrypt (context input-file)
617   "Initiate a decrypt operation on INPUT-FILE.
618
619 If you use this function, you will need to wait for the completion of
620 `epg-gpg-program' by using `epg-wait-for-completion' and call
621 `epg-reset' to clear a temporaly output file.
622 If you are unsure, use synchronous version of this function
623 `epg-decrypt-string' instead."
624   (epg-context-set-result context nil)
625   (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
626   (epg-start context
627              (list "--decrypt" input-file))
628   (epg-wait-for-status context '("BEGIN_DECRYPTION")))
629
630 ;;;###autoload
631 (defun epg-decrypt-file (context input-file)
632   "Decrypt INPUT-FILE and return the plain text."
633   (unwind-protect
634       (progn
635         (epg-start-decrypt context input-file)
636         (epg-wait-for-completion context)
637         (if (epg-context-result-for context 'error)
638             (error "Decryption failed"))
639         (epg-read-output context))
640     (epg-reset context)))
641
642 ;;;###autoload
643 (defun epg-decrypt-string (context string)
644   "Decrypt STRING and return the plain text."
645   (let ((input-file (epg-make-temp-file "epg-input"))
646         (coding-system-for-write 'binary))
647     (unwind-protect
648         (progn
649           (write-region string nil input-file)
650           (epg-decrypt-file context input-file))
651       (if (file-exists-p input-file)
652           (delete-file input-file)))))
653
654 ;;;###autoload
655 (defun epg-start-verify (context signature &optional string)
656   "Initiate a verify operation on SIGNATURE.
657
658 For a detached signature, both SIGNATURE and STRING should be string.
659 For a normal or a clear text signature, STRING should be nil.
660
661 If you use this function, you will need to wait for the completion of
662 `epg-gpg-program' by using `epg-wait-for-completion' and call
663 `epg-reset' to clear a temporaly output file.
664 If you are unsure, use synchronous version of this function
665 `epg-verify-string' instead."
666   (epg-context-set-result context nil)
667   (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
668   (if string
669       ;; Detached signature.
670       (progn
671         (epg-start context
672                    (append (list "--verify")
673                            (list signature "-")))
674         (if (eq (process-status (epg-context-process context)) 'run)
675             (process-send-string (epg-context-process context) string)))
676     ;; Normal (or cleartext) signature.
677     (epg-start context (list "--verify"))
678     (if (eq (process-status (epg-context-process context)) 'run)
679         (process-send-string (epg-context-process context) signature))))
680
681 ;;;###autoload
682 (defun epg-verify-file (context input-file &optional string)
683   "Verify INPUT-FILE.
684
685 For a detached signature, both INPUT-FILE and STRING should be string.
686 For a normal or a clear text signature, STRING should be nil."
687   (unwind-protect
688       (progn
689         (epg-start-verify context input-file string)
690         (epg-wait-for-completion context)
691         (epg-context-result-for context 'verify))
692     (epg-reset context)))
693
694 ;;;###autoload
695 (defun epg-verify-string (context signature &optional string)
696   "Verify SIGNATURE.
697
698 For a detached signature, both SIGNATURE and STRING should be string.
699 For a normal or a clear text signature, STRING should be nil."
700   (let ((input-file (epg-make-temp-file "epg-input"))
701         (coding-system-for-write 'binary))
702     (unwind-protect
703         (progn
704           (if string
705               (write-region signature nil input-file))
706           (epg-verify-file context input-file string))
707       (if (file-exists-p input-file)
708           (delete-file input-file)))))
709
710 ;;;###autoload
711 (defun epg-start-sign (context string &optional mode)
712   "Initiate a sign operation on STRING.
713
714 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
715 If MODE is t or 'detached, it makes a detached signature.
716 Otherwise, it makes a normal signature.
717
718 If you use this function, you will need to wait for the completion of
719 `epg-gpg-program' by using `epg-wait-for-completion' and call
720 `epg-reset' to clear a temporaly output file.
721 If you are unsure, use synchronous version of this function
722 `epg-sign-string' instead."
723   (epg-context-set-result context nil)
724   (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
725   (epg-start context
726              (append (list (if (eq mode 'clearsign)
727                                "--clearsign"
728                              (if (or (eq mode t) (eq mode 'detached))
729                                  "--detach-sign"
730                                "--sign")))
731                      (apply #'nconc
732                             (mapcar (lambda (signer)
733                                       (list "-u" signer))
734                                     (epg-context-signers context)))))
735   (epg-wait-for-status context '("BEGIN_SIGNING"))
736   (if (eq (process-status (epg-context-process context)) 'run)
737       (process-send-string (epg-context-process context) string)))
738
739 ;;;###autoload
740 (defun epg-sign-string (context string &optional mode)
741   "Sign STRING and return the output as string.
742 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
743 If MODE is t or 'detached, it makes a detached signature.
744 Otherwise, it makes a normal signature."
745   (unwind-protect
746       (progn
747         (epg-start-sign context string mode)
748         (epg-wait-for-completion context)
749         (if (epg-context-result-for context 'error)
750             (error "Sign failed"))
751         (epg-read-output context))
752     (epg-reset context)))
753
754 ;;;###autoload
755 (defun epg-start-encrypt (context string recipients
756                                   &optional sign always-trust)
757   "Initiate an encrypt operation on STRING.
758 If RECIPIENTS is nil, it performs symmetric encryption.
759
760 If you use this function, you will need to wait for the completion of
761 `epg-gpg-program' by using `epg-wait-for-completion' and call
762 `epg-reset' to clear a temporaly output file.
763 If you are unsure, use synchronous version of this function
764 `epg-encrypt-string' instead."
765   (epg-context-set-result context nil)
766   (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
767   (epg-start context
768              (append (if always-trust '("--always-trust"))
769                      (if recipients '("--encrypt") '("--symmetric"))
770                      (if sign
771                          (cons "--sign"
772                                (apply #'nconc
773                                       (mapcar (lambda (signer)
774                                                 (list "-u" signer))
775                                               (epg-context-signers context)))))
776                      (apply #'nconc
777                             (mapcar (lambda (recipient)
778                                       (list "-r" recipient))
779                                     recipients))))
780   (if sign
781       (epg-wait-for-status context '("BEGIN_SIGNING"))
782     (if (null recipients)
783         (epg-wait-for-status context '("BEGIN_ENCRYPTION"))))
784   (if (eq (process-status (epg-context-process context)) 'run)
785       (process-send-string (epg-context-process context) string)))
786
787 ;;;###autoload
788 (defun epg-encrypt-string (context string recipients
789                                    &optional sign always-trust)
790   "Encrypt STRING.
791 If RECIPIENTS is nil, it performs symmetric encryption."
792   (unwind-protect
793       (progn
794         (epg-start-encrypt context string recipients sign always-trust)
795         (epg-wait-for-completion context)
796         (if (epg-context-result-for context 'error)
797             (error "Encrypt failed"))
798         (epg-read-output context))
799     (epg-reset context)))
800
801 ;;;###autoload
802 (defun epg-start-export-keys (context pattern)
803   "Initiate an export keys operation.
804
805 If you use this function, you will need to wait for the completion of
806 `epg-gpg-program' by using `epg-wait-for-completion' and call
807 `epg-reset' to clear a temporaly output file.
808 If you are unsure, use synchronous version of this function
809 `epg-export-keys' instead."
810   (epg-context-set-result context nil)
811   (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
812   (epg-start context (list "--export" pattern)))
813
814 ;;;###autoload
815 (defun epg-export-keys (context pattern)
816   "Extract public keys matched with PATTERN and return them."
817   (unwind-protect
818       (progn
819         (epg-start-export-keys context pattern)
820         (epg-wait-for-completion context)
821         (if (epg-context-result-for context 'error)
822             (error "Export keys failed"))
823         (epg-read-output context))
824     (epg-reset context)))
825
826 ;;;###autoload
827 (defun epg-start-import-keys (context keys)
828   "Initiate an import key operation.
829
830 If you use this function, you will need to wait for the completion of
831 `epg-gpg-program' by using `epg-wait-for-completion' and call
832 `epg-reset' to clear a temporaly output file.
833 If you are unsure, use synchronous version of this function
834 `epg-import-keys' instead."
835   (epg-context-set-result context nil)
836   (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
837   (epg-start context (list "--import"))
838   (if (eq (process-status (epg-context-process context)) 'run)
839       (process-send-string (epg-context-process context) keys)))
840
841 ;;;###autoload
842 (defun epg-import-keys (context keys)
843   "Add KEYS."
844   (unwind-protect
845       (progn
846         (epg-start-import-keys context keys)
847         (epg-wait-for-completion context)
848         (if (epg-context-result-for context 'error)
849             (error "Import keys failed"))
850         (epg-read-output context))
851     (epg-reset context)))
852
853 (provide 'epg)
854
855 ;;; epg.el ends here