Add docstring.
[elisp/epg.git] / epg.el
1 ;;; epg.el --- the EasyPG Library
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   "The EasyPG Library")
30
31 (defcustom epg-gpg-program "gpg"
32   "The `gpg' executable."
33   :group 'epg
34   :type 'string)
35
36 (defcustom epg-gpgsm-program "gpgsm"
37   "The `gpgsm' executable."
38   :group 'epg
39   :type 'string)
40
41 (defconst epg-version-number "0.0.0")
42
43 (defvar epg-user-id nil
44   "GnuPG ID of your default identity.")
45
46 (defvar epg-user-id-alist nil
47   "An alist mapping from key ID to user ID.")
48
49 (defvar epg-read-point nil)
50 (defvar epg-pending-status-list nil)
51 (defvar epg-key-id nil)
52 (defvar epg-context nil)
53 (defvar epg-debug nil)
54 (defvar epg-debug-buffer nil)
55
56 ;; from gnupg/include/cipher.h
57 (defconst epg-cipher-algorithm-alist
58   '((0 . "NONE")
59     (1 . "IDEA")
60     (2 . "3DES")
61     (3 . "CAST5")
62     (4 . "BLOWFISH")
63     (7 . "AES")
64     (8 . "AES192")
65     (9 . "AES256")
66     (10 . "TWOFISH")
67     (110 . "DUMMY")))
68
69 ;; from gnupg/include/cipher.h
70 (defconst epg-pubkey-algorithm-alist
71   '((1 . "RSA")
72     (2 . "RSA_E")
73     (3 . "RSA_S")
74     (16 . "ELGAMAL_E")
75     (17 . "DSA")
76     (20 . "ELGAMAL")))
77
78 ;; from gnupg/include/cipher.h
79 (defconst epg-digest-algorithm-alist
80   '((1 . "MD5")
81     (2 . "SHA1")
82     (3 . "RMD160")
83     (8 . "SHA256")
84     (9 . "SHA384")
85     (10 . "SHA512")))
86
87 ;; from gnupg/include/cipher.h
88 (defconst epg-compress-algorithm-alist
89   '((0 . "NONE")
90     (1 . "ZIP")
91     (2 . "ZLIB")
92     (3 . "BZIP2")))
93
94 (defconst epg-invalid-recipients-alist
95   '((0 . "No specific reason given")
96     (1 . "Not Found")
97     (2 . "Ambigious specification")
98     (3 . "Wrong key usage")
99     (4 . "Key revoked")
100     (5 . "Key expired")
101     (6 . "No CRL known")
102     (7 . "CRL too old")
103     (8 . "Policy mismatch")
104     (9 . "Not a secret key")
105     (10 . "Key not trusted")))
106
107 (defconst epg-delete-problem-alist
108   '((1 . "No such key")
109     (2 . "Must delete secret key first")
110     (3 . "Ambigious specification")))
111
112 (defvar epg-key-validity-alist
113   '((?o . unknown)
114     (?i . invalid)
115     (?d . disabled)
116     (?r . revoked)
117     (?e . expired)
118     (?- . none)
119     (?q . undefined)
120     (?n . never)
121     (?m . marginal)
122     (?f . full)
123     (?u . ultimate)))
124
125 (defvar epg-key-capablity-alist
126   '((?e . encrypt)
127     (?s . sign)
128     (?c . certify)
129     (?a . authentication)))
130
131 (defvar epg-dn-type-alist
132   '(("1.2.840.113549.1.9.1" . "EMail")
133     ("2.5.4.12" . "T")
134     ("2.5.4.42" . "GN")
135     ("2.5.4.4" . "SN")
136     ("0.2.262.1.10.7.20" . "NameDistinguisher")
137     ("2.5.4.16" . "ADDR")
138     ("2.5.4.15" . "BC")
139     ("2.5.4.13" . "D")
140     ("2.5.4.17" . "PostalCode")
141     ("2.5.4.65" . "Pseudo")
142     ("2.5.4.5" . "SerialNumber")))
143
144 (defvar epg-prompt-alist nil)
145
146 (defun epg-make-data-from-file (file)
147   "Make a data object from FILE."
148   (vector file nil))
149
150 (defun epg-make-data-from-string (string)
151   "Make a data object from STRING."
152   (vector nil string))
153
154 (defun epg-data-file (data)
155   "Return the file of DATA."
156   (aref data 0))
157
158 (defun epg-data-string (data)
159   "Return the string of DATA."
160   (aref data 1))
161
162 (defun epg-make-context (&optional protocol armor textmode include-certs
163                                    cipher-algorithm digest-algorithm
164                                    compress-algorithm)
165   "Return a context object."
166   (vector protocol armor textmode include-certs
167           cipher-algorithm digest-algorithm compress-algorithm
168           #'epg-passphrase-callback-function
169           #'epg-progress-callback-function
170           nil nil nil nil))
171
172 (defun epg-context-protocol (context)
173   "Return the protocol used within CONTEXT."
174   (aref context 0))
175
176 (defun epg-context-armor (context)
177   "Return t if the output shouled be ASCII armored in CONTEXT."
178   (aref context 1))
179
180 (defun epg-context-textmode (context)
181   "Return t if canonical text mode should be used in CONTEXT."
182   (aref context 2))
183
184 (defun epg-context-include-certs (context)
185   "Return how many certificates should be included in an S/MIME signed
186 message."
187   (aref context 3))
188
189 (defun epg-context-cipher-algorithm (context)
190   "Return the cipher algorithm in CONTEXT."
191   (aref context 4))
192
193 (defun epg-context-digest-algorithm (context)
194   "Return the digest algorithm in CONTEXT."
195   (aref context 5))
196
197 (defun epg-context-compress-algorithm (context)
198   "Return the compress algorithm in CONTEXT."
199   (aref context 6))
200
201 (defun epg-context-passphrase-callback (context)
202   "Return the function used to query passphrase."
203   (aref context 7))
204
205 (defun epg-context-progress-callback (context)
206   "Return the function which handles progress update."
207   (aref context 8))
208
209 (defun epg-context-signers (context)
210   "Return the list of key-id for singning."
211   (aref context 9))
212
213 (defun epg-context-process (context)
214   "Return the process object of `epg-gpg-program'.
215 This function is for internal use only."
216   (aref context 10))
217
218 (defun epg-context-output-file (context)
219   "Return the output file of `epg-gpg-program'.
220 This function is for internal use only."
221   (aref context 11))
222
223 (defun epg-context-result (context)
224   "Return the result of the previous cryptographic operation."
225   (aref context 12))
226
227 (defun epg-context-set-protocol (context protocol)
228   "Set the protocol used within CONTEXT."
229   (aset context 0 protocol))
230
231 (defun epg-context-set-armor (context armor)
232   "Specify if the output shouled be ASCII armored in CONTEXT."
233   (aset context 1 armor))
234
235 (defun epg-context-set-textmode (context textmode)
236   "Specify if canonical text mode should be used in CONTEXT."
237   (aset context 2 textmode))
238
239 (defun epg-context-set-include-certs (context include-certs)
240  "Set how many certificates should be included in an S/MIME signed message."
241   (aset context 3 include-certs))
242
243 (defun epg-context-set-cipher-algorithm (context cipher-algorithm)
244  "Set the cipher algorithm in CONTEXT."
245   (aset context 4 cipher-algorithm))
246
247 (defun epg-context-set-digest-algorithm (context digest-algorithm)
248  "Set the digest algorithm in CONTEXT."
249   (aset context 5 digest-algorithm))
250
251 (defun epg-context-set-compress-algorithm (context compress-algorithm)
252  "Set the compress algorithm in CONTEXT."
253   (aset context 6 compress-algorithm))
254
255 (defun epg-context-set-passphrase-callback (context
256                                                  passphrase-callback)
257   "Set the function used to query passphrase."
258   (aset context 7 passphrase-callback))
259
260 (defun epg-context-set-progress-callback (context progress-callback)
261   "Set the function which handles progress update."
262   (aset context 8 progress-callback))
263
264 (defun epg-context-set-signers (context signers)
265  "Set the list of key-id for singning."
266   (aset context 9 signers))
267
268 (defun epg-context-set-process (context process)
269   "Set the process object of `epg-gpg-program'.
270 This function is for internal use only."
271   (aset context 10 process))
272
273 (defun epg-context-set-output-file (context output-file)
274   "Set the output file of `epg-gpg-program'.
275 This function is for internal use only."
276   (aset context 11 output-file))
277
278 (defun epg-context-set-result (context result)
279   "Set the result of the previous cryptographic operation."
280   (aset context 12 result))
281
282 (defun epg-make-signature (status key-id user-id)
283   "Return a signature object."
284   (vector status key-id user-id nil nil))
285
286 (defun epg-signature-status (signature)
287   "Return the status code of SIGNATURE."
288   (aref signature 0))
289
290 (defun epg-signature-key-id (signature)
291   "Return the key-id of SIGNATURE."
292   (aref signature 1))
293
294 (defun epg-signature-user-id (signature)
295   "Return the user-id of SIGNATURE."
296   (aref signature 2))
297   
298 (defun epg-signature-validity (signature)
299   "Return the validity of SIGNATURE."
300   (aref signature 3))
301
302 (defun epg-signature-fingerprint (signature)
303   "Return the fingerprint of SIGNATURE."
304   (aref signature 4))
305
306 (defun epg-signature-set-status (signature status)
307  "Set the status code of SIGNATURE."
308   (aset signature 0 status))
309
310 (defun epg-signature-set-key-id (signature key-id)
311  "Set the key-id of SIGNATURE."
312   (aset signature 1 key-id))
313
314 (defun epg-signature-set-user-id (signature user-id)
315  "Set the user-id of SIGNATURE."
316   (aset signature 2 user-id))
317   
318 (defun epg-signature-set-validity (signature validity)
319  "Set the validity of SIGNATURE."
320   (aset signature 3 validity))
321
322 (defun epg-signature-set-fingerprint (signature fingerprint)
323  "Set the fingerprint of SIGNATURE."
324   (aset signature 4 fingerprint))
325
326 (defun epg-make-key (owner-trust)
327   "Return a key object."
328   (vector owner-trust nil nil))
329
330 (defun epg-key-owner-trust (key)
331   "Return the owner trust of KEY."
332   (aref key 0))
333
334 (defun epg-key-sub-key-list (key)
335   "Return the sub key list of KEY."
336   (aref key 1))
337
338 (defun epg-key-user-id-list (key)
339   "Return the user ID list of KEY."
340   (aref key 2))
341
342 (defun epg-key-set-sub-key-list (key sub-key-list)
343   "Set the sub key list of KEY."
344   (aset key 1 sub-key-list))
345
346 (defun epg-key-set-user-id-list (key user-id-list)
347   "Set the user ID list of KEY."
348   (aset key 2 user-id-list))
349
350 (defun epg-make-sub-key (validity capability secret algorithm length id
351                                   creation-time expiration-time)
352   "Return a sub key object."
353   (vector validity capability secret algorithm length id creation-time
354           expiration-time nil))
355
356 (defun epg-sub-key-validity (sub-key)
357   "Return the validity of SUB-KEY."
358   (aref sub-key 0))
359
360 (defun epg-sub-key-capability (sub-key)
361   "Return the capability of SUB-KEY."
362   (aref sub-key 1))
363
364 (defun epg-sub-key-secret (sub-key)
365   "Return non-nil if SUB-KEY is a secret key."
366   (aref sub-key 2))
367
368 (defun epg-sub-key-algorithm (sub-key)
369   "Return the algorithm of SUB-KEY."
370   (aref sub-key 3))
371
372 (defun epg-sub-key-length (sub-key)
373   "Return the length of SUB-KEY."
374   (aref sub-key 4))
375
376 (defun epg-sub-key-id (sub-key)
377   "Return the ID of SUB-KEY."
378   (aref sub-key 5))
379
380 (defun epg-sub-key-creation-time (sub-key)
381   "Return the creation time of SUB-KEY."
382   (aref sub-key 6))
383
384 (defun epg-sub-key-expiration-time (sub-key)
385   "Return the expiration time of SUB-KEY."
386   (aref sub-key 7))
387
388 (defun epg-sub-key-fingerprint (sub-key)
389   "Return the fingerprint of SUB-KEY."
390   (aref sub-key 8))
391
392 (defun epg-sub-key-set-fingerprint (sub-key fingerprint)
393   "Set the fingerprint of SUB-KEY.
394 This function is for internal use only."
395   (aset sub-key 8 fingerprint))
396
397 (defun epg-make-user-id (validity name)
398   "Return a user ID object."
399   (vector validity name nil))
400
401 (defun epg-user-id-validity (user-id)
402   "Return the validity of USER-ID."
403   (aref user-id 0))
404
405 (defun epg-user-id-name (user-id)
406   "Return the name of USER-ID."
407   (aref user-id 1))
408
409 (defun epg-user-id-signature-list (user-id)
410   "Return the signature list of USER-ID."
411   (aref user-id 2))
412
413 (defun epg-user-id-set-signature-list (user-id signature-list)
414   "Set the signature list of USER-ID."
415   (aset user-id 2 signature-list))
416
417 (defun epg-context-result-for (context name)
418   (cdr (assq name (epg-context-result context))))
419
420 (defun epg-context-set-result-for (context name value)
421   (let* ((result (epg-context-result context))
422          (entry (assq name result)))
423     (if entry
424         (setcdr entry value)
425       (epg-context-set-result context (cons (cons name value) result)))))
426
427 (defun epg-signature-to-string (signature)
428   (format "%s signature from %s %s%s"
429           (capitalize (symbol-name (epg-signature-status signature)))
430           (epg-signature-key-id signature)
431           (epg-signature-user-id signature)
432           (if (epg-signature-validity signature)
433               (format " (trust %s)"
434                       (epg-signature-validity signature))
435             "")))
436
437 (defun epg-verify-result-to-string (verify-result)
438   (mapconcat #'epg-signature-to-string verify-result "\n"))
439
440 (defun epg-start (context args)
441   "Start `epg-gpg-program' in a subprocess with given ARGS."
442   (let* ((args (append (list "--no-tty"
443                              "--status-fd" "1"
444                              "--yes")
445                        (unless (eq (epg-context-protocol context) 'CMS)
446                          (list "--command-fd" "0"))
447                        (if (epg-context-armor context) '("--armor"))
448                        (if (epg-context-textmode context) '("--textmode"))
449                        (if (epg-context-output-file context)
450                            (list "--output" (epg-context-output-file context)))
451                        args))
452          (coding-system-for-write 'binary)
453          process-connection-type
454          (orig-mode (default-file-modes))
455          (buffer (generate-new-buffer " *epg*"))
456          process)
457     (if epg-debug
458         (save-excursion
459           (unless epg-debug-buffer
460             (setq epg-debug-buffer (generate-new-buffer " *epg-debug*")))
461           (set-buffer epg-debug-buffer)
462           (goto-char (point-max))
463           (insert (format "%s %s\n"
464                           (if (eq (epg-context-protocol context) 'CMS)
465                               epg-gpgsm-program
466                            epg-gpg-program)
467                           (mapconcat #'identity args " ")))))
468     (with-current-buffer buffer
469       (make-local-variable 'epg-read-point)
470       (setq epg-read-point (point-min))
471       (make-local-variable 'epg-pending-status-list)
472       (setq epg-pending-status-list nil)
473       (make-local-variable 'epg-key-id)
474       (setq epg-key-id nil)
475       (make-local-variable 'epg-context)
476       (setq epg-context context))
477     (unwind-protect
478         (progn
479           (set-default-file-modes 448)
480           (setq process
481                 (apply #'start-process "epg" buffer
482                        (if (eq (epg-context-protocol context) 'CMS)
483                            epg-gpgsm-program
484                          epg-gpg-program)
485                        args)))
486       (set-default-file-modes orig-mode))
487     (set-process-filter process #'epg-process-filter)
488     (set-process-sentinel process #'epg-process-sentinel)
489     (epg-context-set-process context process)))
490
491 (defun epg-process-filter (process input)
492   (if epg-debug
493       (save-excursion
494         (unless epg-debug-buffer
495           (setq epg-debug-buffer (generate-new-buffer " *epg-debug*")))
496         (set-buffer epg-debug-buffer)
497         (goto-char (point-max))
498         (insert input)))
499   (if (buffer-live-p (process-buffer process))
500       (save-excursion
501         (set-buffer (process-buffer process))
502         (goto-char (point-max))
503         (insert input)
504         (goto-char epg-read-point)
505         (beginning-of-line)
506         (while (looking-at ".*\n")      ;the input line finished
507           (save-excursion
508             (if (looking-at "\\[GNUPG:] \\([A-Z_]+\\) ?\\(.*\\)")
509                 (let* ((status (match-string 1))
510                        (string (match-string 2))
511                        (symbol (intern-soft (concat "epg-status-" status))))
512                   (if (member status epg-pending-status-list)
513                       (setq epg-pending-status-list nil))
514                   (if (and symbol
515                            (fboundp symbol))
516                       (funcall symbol process string)))))
517           (forward-line))
518         (setq epg-read-point (point)))))
519
520 (defun epg-process-sentinel (process status)
521   (if (and (buffer-live-p (process-buffer process))
522            (not (equal status "finished\n")))
523       (save-excursion
524         (set-buffer (process-buffer process))
525         ;; gpg process exited abnormally, but we have not received an
526         ;; error response from it.  Set it here.
527         (unless (epg-context-result-for epg-context 'error)
528           (if (string-match "\\`exited abnormally with code \\(.*\\)\n" status)
529               (epg-context-set-result-for
530                epg-context 'error
531                (list (cons 'exit (string-to-number (match-string 1 status)))))
532             (epg-context-set-result-for epg-context 'error
533                                     (list (cons 'signal status))))))))
534
535 (defun epg-read-output (context)
536   (with-temp-buffer
537     (if (fboundp 'set-buffer-multibyte)
538         (set-buffer-multibyte nil))
539     (if (file-exists-p (epg-context-output-file context))
540         (let ((coding-system-for-read (if (epg-context-textmode context)
541                                           'raw-text
542                                         'binary)))
543           (insert-file-contents (epg-context-output-file context))
544           (buffer-string)))))
545
546 (defun epg-wait-for-status (context status-list)
547   (with-current-buffer (process-buffer (epg-context-process context))
548     (setq epg-pending-status-list status-list)
549     (while (and (eq (process-status (epg-context-process context)) 'run)
550                 epg-pending-status-list)
551       (accept-process-output (epg-context-process context) 1))))
552
553 (defun epg-wait-for-completion (context)
554   (while (eq (process-status (epg-context-process context)) 'run)
555     ;; We can't use accept-process-output instead of sit-for here
556     ;; because it may cause an interrupt during the sentinel execution.
557     (sit-for 0.1)))
558
559 (defun epg-flush (context)
560   (if (eq (process-status (epg-context-process context)) 'run)
561       (process-send-eof (epg-context-process context))))
562
563 (defun epg-reset (context)
564   (if (and (epg-context-process context)
565            (buffer-live-p (process-buffer (epg-context-process context))))
566       (kill-buffer (process-buffer (epg-context-process context))))
567   (epg-context-set-process context nil))
568
569 (defun epg-delete-output-file (context)
570   (if (and (epg-context-output-file context)
571            (file-exists-p (epg-context-output-file context)))
572       (delete-file (epg-context-output-file context))))
573
574 (defun epg-status-USERID_HINT (process string)
575   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
576       (let* ((key-id (match-string 1 string))
577              (user-id (match-string 2 string))
578              (entry (assoc key-id epg-user-id-alist)))
579         (if entry
580             (setcdr entry user-id)
581           (setq epg-user-id-alist (cons (cons key-id user-id)
582                                         epg-user-id-alist))))))
583
584 (defun epg-status-NEED_PASSPHRASE (process string)
585   (if (string-match "\\`\\([^ ]+\\)" string)
586       (setq epg-key-id (match-string 1 string))))
587
588 (defun epg-status-NEED_PASSPHRASE_SYM (process string)
589   (setq epg-key-id 'SYM))
590
591 (defun epg-status-NEED_PASSPHRASE_PIN (process string)
592   (setq epg-key-id 'PIN))
593
594 (defun epg-status-GET_HIDDEN (process string)
595   (if (and epg-key-id
596            (string-match "\\`passphrase\\." string))
597       (let (inhibit-quit
598             passphrase
599             passphrase-with-new-line)
600         (unwind-protect
601             (condition-case nil
602                 (progn
603                   (setq passphrase
604                         (funcall
605                          (if (consp (epg-context-passphrase-callback
606                                      epg-context))
607                              (car (epg-context-passphrase-callback
608                                    epg-context))
609                            (epg-context-passphrase-callback epg-context))
610                          epg-context
611                          epg-key-id
612                          (if (consp (epg-context-passphrase-callback
613                                      epg-context))
614                              (cdr (epg-context-passphrase-callback
615                                    epg-context)))))
616                   (when passphrase
617                     (setq passphrase-with-new-line (concat passphrase "\n"))
618                     (fillarray passphrase 0)
619                     (setq passphrase nil)
620                     (process-send-string process passphrase-with-new-line)))
621               (quit
622                (epg-context-set-result-for
623                 epg-context 'error
624                 (cons 'quit
625                       (epg-context-result-for epg-context 'error)))
626                (delete-process process)))
627           (if passphrase
628               (fillarray passphrase 0))
629           (if passphrase-with-new-line
630               (fillarray passphrase-with-new-line 0))))))
631
632 (defun epg-status-GET_BOOL (process string)
633   (let ((entry (assoc string epg-prompt-alist))
634         inhibit-quit)
635     (condition-case nil
636       (if (y-or-n-p (if entry (cdr entry) (concat string "? ")))
637           (process-send-string process "y\n")
638         (process-send-string process "n\n"))
639       (quit
640        (epg-context-set-result-for
641         epg-context 'error
642         (cons 'quit
643               (epg-context-result-for epg-context 'error)))
644        (delete-process process)))))
645
646 (defun epg-status-GET_LINE (process string)
647   (let ((entry (assoc string epg-prompt-alist))
648         inhibit-quit)
649     (condition-case nil
650         (process-send-string
651          process
652          (concat (read-string (if entry (cdr entry) (concat string ": ")))
653                  "\n"))
654       (quit
655        (epg-context-set-result-for
656         epg-context 'error
657         (cons 'quit
658               (epg-context-result-for epg-context 'error)))
659        (delete-process process)))))
660
661 (defun epg-status-GOODSIG (process string)
662   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
663       (epg-context-set-result-for
664        epg-context
665        'verify
666        (cons (epg-make-signature
667               'good
668               (match-string 1 string)
669               (if (eq (epg-context-protocol epg-context) 'CMS)
670                   (condition-case nil
671                       (epg-dn-from-string (match-string 2 string))
672                     (error (match-string 2 string)))
673                 (match-string 2 string)))
674              (epg-context-result-for epg-context 'verify)))))
675
676 (defun epg-status-EXPSIG (process string)
677   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
678       (epg-context-set-result-for
679        epg-context
680        'verify
681        (cons (epg-make-signature
682               'expired
683               (match-string 1 string)
684               (if (eq (epg-context-protocol epg-context) 'CMS)
685                   (condition-case nil
686                       (epg-dn-from-string (match-string 2 string))
687                     (error (match-string 2 string)))
688                 (match-string 2 string)))
689              (epg-context-result-for epg-context 'verify)))))
690
691 (defun epg-status-EXPKEYSIG (process string)
692   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
693       (epg-context-set-result-for
694        epg-context
695        'verify
696        (cons (epg-make-signature
697               'expired-key
698               (match-string 1 string)
699               (if (eq (epg-context-protocol epg-context) 'CMS)
700                   (condition-case nil
701                       (epg-dn-from-string (match-string 2 string))
702                     (error (match-string 2 string)))
703                 (match-string 2 string)))
704              (epg-context-result-for epg-context 'verify)))))
705
706 (defun epg-status-REVKEYSIG (process string)
707   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
708       (epg-context-set-result-for
709        epg-context
710        'verify
711        (cons (epg-make-signature
712               'revoked-key
713               (match-string 1 string)
714               (if (eq (epg-context-protocol epg-context) 'CMS)
715                   (condition-case nil
716                       (epg-dn-from-string (match-string 2 string))
717                     (error (match-string 2 string)))
718                 (match-string 2 string)))
719              (epg-context-result-for epg-context 'verify)))))
720
721 (defun epg-status-BADSIG (process string)
722   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
723       (epg-context-set-result-for
724        epg-context
725        'verify
726        (cons (epg-make-signature
727               'bad
728               (match-string 1 string)
729               (if (eq (epg-context-protocol epg-context) 'CMS)
730                   (condition-case nil
731                       (epg-dn-from-string (match-string 2 string))
732                     (error (match-string 2 string)))
733                 (match-string 2 string)))
734              (epg-context-result-for epg-context 'verify)))))
735
736 (defun epg-status-VALIDSIG (process string)
737   (let ((signature (car (epg-context-result-for epg-context 'verify))))
738     (if (and signature
739              (eq (epg-signature-status signature) 'good)
740              (string-match "\\`\\([^ ]+\\) " string))
741         (epg-signature-set-fingerprint signature (match-string 1 string)))))
742
743 (defun epg-status-TRUST_UNDEFINED (process string)
744   (let ((signature (car (epg-context-result-for epg-context 'verify))))
745     (if (and signature
746              (eq (epg-signature-status signature) 'good))
747         (epg-signature-set-validity signature 'undefined))))
748
749 (defun epg-status-TRUST_NEVER (process string)
750   (let ((signature (car (epg-context-result-for epg-context 'verify))))
751     (if (and signature
752              (eq (epg-signature-status signature) 'good))
753         (epg-signature-set-validity signature 'never))))
754
755 (defun epg-status-TRUST_MARGINAL (process string)
756   (let ((signature (car (epg-context-result-for epg-context 'verify))))
757     (if (and signature
758              (eq (epg-signature-status signature) 'marginal))
759         (epg-signature-set-validity signature 'marginal))))
760
761 (defun epg-status-TRUST_FULLY (process string)
762   (let ((signature (car (epg-context-result-for epg-context 'verify))))
763     (if (and signature
764              (eq (epg-signature-status signature) 'good))
765         (epg-signature-set-validity signature 'full))))
766
767 (defun epg-status-TRUST_ULTIMATE (process string)
768   (let ((signature (car (epg-context-result-for epg-context 'verify))))
769     (if (and signature
770              (eq (epg-signature-status signature) 'good))
771         (epg-signature-set-validity signature 'ultimate))))
772
773 (defun epg-status-PROGRESS (process string)
774   (if (string-match "\\`\\([^ ]+\\) \\([^ ]\\) \\([0-9]+\\) \\([0-9]+\\)"
775                     string)
776       (funcall (if (consp (epg-context-progress-callback epg-context))
777                    (car (epg-context-progress-callback epg-context))
778                  (epg-context-progress-callback epg-context))
779                epg-context
780                (match-string 1 string)
781                (match-string 2 string)
782                (string-to-number (match-string 3 string))
783                (string-to-number (match-string 4 string))
784                (if (consp (epg-context-progress-callback epg-context))
785                    (cdr (epg-context-progress-callback epg-context))))))
786
787 (defun epg-status-DECRYPTION_FAILED (process string)
788   (epg-context-set-result-for
789    epg-context 'error
790    (cons 'decryption-failed
791          (epg-context-result-for epg-context 'error))))
792
793 (defun epg-status-NODATA (process string)
794   (epg-context-set-result-for
795    epg-context 'error
796    (cons (cons 'no-data (string-to-number string))
797          (epg-context-result-for epg-context 'error))))
798
799 (defun epg-status-UNEXPECTED (process string)
800   (epg-context-set-result-for
801    epg-context 'error
802    (cons (cons 'unexpected (string-to-number string))
803          (epg-context-result-for epg-context 'error))))
804
805 (defun epg-status-KEYEXPIRED (process string)
806   (epg-context-set-result-for
807    epg-context 'error
808    (cons (cons 'key-expired string)
809          (epg-context-result-for epg-context 'error))))
810
811 (defun epg-status-KEYREVOKED (process string)
812   (epg-context-set-result-for
813    epg-context 'error
814    (cons 'key-revoked
815          (epg-context-result-for epg-context 'error))))
816
817 (defun epg-status-BADARMOR (process string)
818   (epg-context-set-result-for
819    epg-context 'error
820    (cons 'bad-armor
821          (epg-context-result-for epg-context 'error))))
822
823 (defun epg-status-INV_RECP (process string)
824   (if (string-match "\\`\\([0-9]+\\) \\(.*\\)" string)
825       (epg-context-set-result-for
826        epg-context 'error
827        (cons (list 'invalid-recipient
828                    (string-to-number (match-string 1 string))
829                    (match-string 2 string))
830              (epg-context-result-for epg-context 'error)))))
831
832 (defun epg-status-NO_RECP (process string)
833   (epg-context-set-result-for
834    epg-context 'error
835    (cons 'no-recipients
836          (epg-context-result-for epg-context 'error))))
837
838 (defun epg-status-DELETE_PROBLEM (process string)
839   (if (string-match "\\`\\([0-9]+\\)" string)
840       (epg-context-set-result-for
841        epg-context 'error
842        (cons (cons 'delete-problem (string-to-number (match-string 1 string)))
843              (epg-context-result-for epg-context 'error)))))
844
845 (defun epg-status-SIG_CREATED (process string)
846   (if (string-match "\\`\\([DCS]\\) \\([0-9]+\\) \\([0-9]+\\) \
847 \\([0-9A-Fa-F][0-9A-Fa-F]\\) \\(.*\\) " string)
848       (epg-context-set-result-for
849        epg-context 'sign
850        (cons (list (cons 'type (string-to-char (match-string 1 string)))
851                    (cons 'pubkey-algorithm
852                          (string-to-number (match-string 2 string)))
853                    (cons 'digest-algorithm
854                          (string-to-number (match-string 3 string)))
855                    (cons 'class (string-to-number (match-string 4 string) 16))
856                    (cons 'creation-time (match-string 5 string))
857                    (cons 'fingerprint (substring string (match-end 0))))
858              (epg-context-result-for epg-context 'sign)))))
859
860 (defun epg-passphrase-callback-function (context key-id handback)
861   (read-passwd
862    (if (eq key-id 'SYM)
863        "Passphrase for symmetric encryption: "
864      (if (eq key-id 'PIN)
865          "Passphrase for PIN: "
866        (let ((entry (assoc key-id epg-user-id-alist)))
867          (if entry
868              (format "Passphrase for %s %s: " key-id (cdr entry))
869            (format "Passphrase for %s: " key-id)))))))
870
871 (defun epg-progress-callback-function (context what char current total
872                                                handback)
873   (message "%s: %d%%/%d%%" what current total))
874
875 (defun epg-configuration ()
876   "Return a list of internal configuration parameters of `epg-gpg-program'."
877   (let (config type)
878     (with-temp-buffer
879       (apply #'call-process epg-gpg-program nil (list t nil) nil
880              '("--with-colons" "--list-config"))
881       (goto-char (point-min))
882       (while (re-search-forward "^cfg:\\([^:]+\\):\\(.*\\)" nil t)
883         (setq type (intern (match-string 1))
884               config (cons (cons type
885                                  (if (memq type
886                                            '(pubkey cipher digest compress))
887                                      (mapcar #'string-to-number
888                                              (delete "" (split-string
889                                                          (match-string 2)
890                                                          ";")))
891                                    (match-string 2)))
892                            config))))
893     config))
894
895 (defun epg-list-keys-1 (context name mode)
896   (let ((args (append (list "--with-colons" "--no-greeting" "--batch"
897                             "--with-fingerprint"
898                             "--with-fingerprint"
899                             (if (or (eq mode t) (eq mode 'secret))
900                                 "--list-secret-keys"
901                               (if mode
902                                   "--list-sigs"
903                                 "--list-keys")))
904                       (unless (eq (epg-context-protocol context) 'CMS)
905                         '("--fixed-list-mode"))
906                       (if name (list name))))
907         keys string field index)
908     (with-temp-buffer
909       (apply #'call-process
910              (if (eq (epg-context-protocol context) 'CMS)
911                  epg-gpgsm-program
912                epg-gpg-program)
913              nil (list t nil) nil args)
914       (goto-char (point-min))
915       (while (re-search-forward "^[a-z][a-z][a-z]:.*" nil t)
916         (setq keys (cons (make-vector 15 nil) keys)
917               string (match-string 0)
918               index 0
919               field 0)
920         (while (eq index
921                    (string-match "\\([^:]+\\)?:" string index))
922           (setq index (match-end 0))
923           (aset (car keys) field (match-string 1 string))
924           (setq field (1+ field))))
925       (nreverse keys))))
926
927 (defun epg-make-sub-key-1 (line)
928   (epg-make-sub-key
929    (if (aref line 1)
930        (cdr (assq (string-to-char (aref line 1)) epg-key-validity-alist)))
931    (delq nil
932          (mapcar (lambda (char) (cdr (assq char epg-key-capablity-alist)))
933                  (aref line 11)))
934    (member (aref line 0) '("sec" "ssb"))
935    (string-to-number (aref line 3))
936    (string-to-number (aref line 2))
937    (aref line 4)
938    (aref line 5)
939    (aref line 6)))
940
941 (defun epg-list-keys (context &optional name mode)
942   "Return a list of epg-key objects matched with NAME.
943 If MODE is nil, only public keyring should be searched.
944 If MODE is t or 'secret, only secret keyring should be searched. 
945 Otherwise, only public keyring should be searched and the key
946 signatures should be included."
947   (let ((lines (epg-list-keys-1 context name mode))
948         keys cert)
949     (while lines
950       (cond
951        ((member (aref (car lines) 0) '("pub" "sec" "crt" "crs"))
952         (when (car keys)
953           (epg-key-set-sub-key-list
954            (car keys)
955            (nreverse (epg-key-sub-key-list (car keys))))
956           (epg-key-set-user-id-list
957            (car keys)
958            (nreverse (epg-key-user-id-list (car keys)))))
959         (setq cert (member (aref (car lines) 0) '("crt" "crs"))
960               keys (cons (epg-make-key
961                           (if (aref (car lines) 8)
962                               (cdr (assq (string-to-char (aref (car lines) 8))
963                                          epg-key-validity-alist))))
964                          keys))
965         (epg-key-set-sub-key-list
966          (car keys)
967          (cons (epg-make-sub-key-1 (car lines))
968                (epg-key-sub-key-list (car keys)))))
969        ((member (aref (car lines) 0) '("sub" "ssb"))
970         (epg-key-set-sub-key-list
971          (car keys)
972          (cons (epg-make-sub-key-1 (car lines))
973                (epg-key-sub-key-list (car keys)))))
974        ((equal (aref (car lines) 0) "uid")
975         (epg-key-set-user-id-list
976          (car keys)
977          (cons (epg-make-user-id
978                 (if (aref (car lines) 1)
979                     (cdr (assq (string-to-char (aref (car lines) 1))
980                                epg-key-validity-alist)))
981                 (if cert
982                     (condition-case nil
983                         (epg-dn-from-string (aref (car lines) 9))
984                       (error (aref (car lines) 9)))
985                   (aref (car lines) 9)))
986                (epg-key-user-id-list (car keys)))))
987        ((equal (aref (car lines) 0) "fpr")
988         (epg-sub-key-set-fingerprint (car (epg-key-sub-key-list (car keys)))
989                                      (aref (car lines) 9))))
990       (setq lines (cdr lines)))
991     (when (car keys)
992       (epg-key-set-sub-key-list
993        (car keys)
994        (nreverse (epg-key-sub-key-list (car keys))))
995       (epg-key-set-user-id-list
996        (car keys)
997        (nreverse (epg-key-user-id-list (car keys)))))
998     (nreverse keys)))
999
1000 (if (fboundp 'make-temp-file)
1001     (defalias 'epg-make-temp-file 'make-temp-file)
1002   ;; stolen from poe.el.
1003   (defun epg-make-temp-file (prefix)
1004     "Create a temporary file.
1005 The returned file name (created by appending some random characters at the end
1006 of PREFIX, and expanding against `temporary-file-directory' if necessary),
1007 is guaranteed to point to a newly created empty file.
1008 You can then use `write-region' to write new data into the file."
1009     (let (tempdir tempfile)
1010       (unwind-protect
1011           (let (file)
1012             ;; First, create a temporary directory.
1013             (while (condition-case ()
1014                        (progn
1015                          (setq tempdir (make-temp-name
1016                                         (concat
1017                                          (file-name-directory prefix)
1018                                          "DIR")))
1019                          ;; return nil or signal an error.
1020                          (make-directory tempdir))
1021                      ;; let's try again.
1022                      (file-already-exists t)))
1023             (set-file-modes tempdir 448)
1024             ;; Second, create a temporary file in the tempdir.
1025             ;; There *is* a race condition between `make-temp-name'
1026             ;; and `write-region', but we don't care it since we are
1027             ;; in a private directory now.
1028             (setq tempfile (make-temp-name (concat tempdir "/EMU")))
1029             (write-region "" nil tempfile nil 'silent)
1030             (set-file-modes tempfile 384)
1031             ;; Finally, make a hard-link from the tempfile.
1032             (while (condition-case ()
1033                        (progn
1034                          (setq file (make-temp-name prefix))
1035                          ;; return nil or signal an error.
1036                          (add-name-to-file tempfile file))
1037                      ;; let's try again.
1038                      (file-already-exists t)))
1039             file)
1040         ;; Cleanup the tempfile.
1041         (and tempfile
1042              (file-exists-p tempfile)
1043              (delete-file tempfile))
1044         ;; Cleanup the tempdir.
1045         (and tempdir
1046              (file-directory-p tempdir)
1047              (delete-directory tempdir))))))
1048
1049 ;;;###autoload
1050 (defun epg-cancel (context)
1051   (if (eq (process-status (epg-context-process context)) 'run)
1052       (delete-process (epg-context-process context))))
1053   
1054 ;;;###autoload
1055 (defun epg-start-decrypt (context cipher)
1056   "Initiate a decrypt operation on CIPHER.
1057 CIPHER is a data object.
1058
1059 If you use this function, you will need to wait for the completion of
1060 `epg-gpg-program' by using `epg-wait-for-completion' and call
1061 `epg-reset' to clear a temporaly output file.
1062 If you are unsure, use synchronous version of this function
1063 `epg-decrypt-file' or `epg-decrypt-string' instead."
1064   (unless (epg-data-file cipher)
1065     (error "Not a file"))
1066   (epg-context-set-result context nil)
1067   (epg-start context (list "--decrypt" (epg-data-file cipher)))
1068   ;; `gpgsm' does not read passphrase from stdin, so waiting is not needed.
1069   (unless (eq (epg-context-protocol context) 'CMS)
1070     (epg-wait-for-status context '("BEGIN_DECRYPTION"))))
1071
1072 ;;;###autoload
1073 (defun epg-decrypt-file (context cipher plain)
1074   "Decrypt a file CIPHER and store the result to a file PLAIN.
1075 If PLAIN is nil, it returns the result as a string."
1076   (unwind-protect
1077       (progn
1078         (if plain
1079             (epg-context-set-output-file context plain)
1080           (epg-context-set-output-file context
1081                                        (epg-make-temp-file "epg-output")))
1082         (epg-start-decrypt context (epg-make-data-from-file cipher))
1083         (epg-wait-for-completion context)
1084         (if (epg-context-result-for context 'error)
1085             (error "Decrypt failed: %S"
1086                    (epg-context-result-for context 'error)))
1087         (unless plain
1088           (epg-read-output context)))
1089     (unless plain
1090       (epg-delete-output-file context))
1091     (epg-reset context)))
1092
1093 ;;;###autoload
1094 (defun epg-decrypt-string (context cipher)
1095   "Decrypt a string CIPHER and return the plain text."
1096   (let ((input-file (epg-make-temp-file "epg-input"))
1097         (coding-system-for-write 'binary))
1098     (unwind-protect
1099         (progn
1100           (write-region cipher nil input-file nil 'quiet)
1101           (epg-context-set-output-file context
1102                                        (epg-make-temp-file "epg-output"))
1103           (epg-start-decrypt context (epg-make-data-from-file input-file))
1104           (epg-flush context)
1105           (epg-wait-for-completion context)
1106           (if (epg-context-result-for context 'error)
1107               (error "Decrypt failed: %S"
1108                      (epg-context-result-for context 'error)))
1109           (epg-read-output context))
1110       (epg-delete-output-file context)
1111       (if (file-exists-p input-file)
1112           (delete-file input-file))
1113       (epg-reset context))))
1114
1115 ;;;###autoload
1116 (defun epg-start-verify (context signature &optional signed-text)
1117   "Initiate a verify operation on SIGNATURE.
1118 SIGNATURE and SIGNED-TEXT are a data object if they are specified.
1119
1120 For a detached signature, both SIGNATURE and SIGNED-TEXT should be set.
1121 For a normal or a clear text signature, SIGNED-TEXT should be nil.
1122
1123 If you use this function, you will need to wait for the completion of
1124 `epg-gpg-program' by using `epg-wait-for-completion' and call
1125 `epg-reset' to clear a temporaly output file.
1126 If you are unsure, use synchronous version of this function
1127 `epg-verify-file' or `epg-verify-string' instead."
1128   (epg-context-set-result context nil)
1129   (if signed-text
1130       ;; Detached signature.
1131       (if (epg-data-file signed-text)
1132           (epg-start context (list "--verify" (epg-data-file signature)
1133                                    (epg-data-file signed-text)))
1134         (epg-start context (list "--verify" (epg-data-file signature) "-"))
1135         (if (eq (process-status (epg-context-process context)) 'run)
1136             (process-send-string (epg-context-process context)
1137                                  (epg-data-string signed-text))))
1138     ;; Normal (or cleartext) signature.
1139     (if (epg-data-file signature)
1140         (epg-start context (list "--verify" (epg-data-file signature)))
1141       (epg-start context (list "--verify"))
1142       (if (eq (process-status (epg-context-process context)) 'run)
1143           (process-send-string (epg-context-process context)
1144                                (epg-data-string signature))))))
1145
1146 ;;;###autoload
1147 (defun epg-verify-file (context signature &optional signed-text plain)
1148   "Verify a file SIGNATURE.
1149 SIGNED-TEXT and PLAIN are also a file if they are specified.
1150
1151 For a detached signature, both SIGNATURE and SIGNED-TEXT should be string.
1152 For a normal or a clear text signature, SIGNED-TEXT should be nil."
1153   (unwind-protect
1154       (progn
1155         (if plain
1156             (epg-context-set-output-file context plain)
1157           (epg-context-set-output-file context
1158                                        (epg-make-temp-file "epg-output")))
1159         (if signed-text
1160             (epg-start-verify context
1161                               (epg-make-data-from-file signature)
1162                               (epg-make-data-from-file signed-text))
1163           (epg-start-verify context
1164                             (epg-make-data-from-file signature)))
1165         (epg-wait-for-completion context)
1166         (unless plain
1167           (epg-read-output context)))
1168     (unless plain
1169       (epg-delete-output-file context))
1170     (epg-reset context)))
1171
1172 ;;;###autoload
1173 (defun epg-verify-string (context signature &optional signed-text)
1174   "Verify a string SIGNATURE.
1175 SIGNED-TEXT is a string if it is specified.
1176
1177 For a detached signature, both SIGNATURE and SIGNED-TEXT should be string.
1178 For a normal or a clear text signature, SIGNED-TEXT should be nil."
1179   (let ((coding-system-for-write 'binary)
1180         input-file)
1181     (unwind-protect
1182         (progn
1183           (epg-context-set-output-file context
1184                                        (epg-make-temp-file "epg-output"))
1185           (if signed-text
1186               (progn
1187                 (setq input-file (epg-make-temp-file "epg-signature"))
1188                 (write-region signature nil input-file nil 'quiet)
1189                 (epg-start-verify context
1190                                   (epg-make-data-from-file input-file)
1191                                   (epg-make-data-from-string signed-text)))
1192             (epg-start-verify context (epg-make-data-from-string signature)))
1193           (epg-flush context)
1194           (epg-wait-for-completion context)
1195           (epg-read-output context))
1196       (epg-delete-output-file context)
1197       (if (and input-file
1198                (file-exists-p input-file))
1199           (delete-file input-file))
1200       (epg-reset context))))
1201
1202 ;;;###autoload
1203 (defun epg-start-sign (context plain &optional mode)
1204   "Initiate a sign operation on PLAIN.
1205 PLAIN is a data object.
1206
1207 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
1208 If MODE is t or 'detached, it makes a detached signature.
1209 Otherwise, it makes a normal signature.
1210
1211 If you use this function, you will need to wait for the completion of
1212 `epg-gpg-program' by using `epg-wait-for-completion' and call
1213 `epg-reset' to clear a temporaly output file.
1214 If you are unsure, use synchronous version of this function
1215 `epg-sign-file' or `epg-sign-string' instead."
1216   (epg-context-set-result context nil)
1217   (epg-start context
1218              (append (list (if (eq mode 'clearsign)
1219                                "--clearsign"
1220                              (if (or (eq mode t) (eq mode 'detached))
1221                                  "--detach-sign"
1222                                "--sign")))
1223                      (apply #'nconc
1224                             (mapcar
1225                              (lambda (signer)
1226                                (list "-u"
1227                                      (epg-sub-key-id
1228                                       (car (epg-key-sub-key-list signer)))))
1229                              (epg-context-signers context)))
1230                      (if (epg-data-file plain)
1231                          (list (epg-data-file plain)))))
1232   ;; `gpgsm' does not read passphrase from stdin, so waiting is not needed.
1233   (unless (eq (epg-context-protocol context) 'CMS)
1234     (epg-wait-for-status context '("BEGIN_SIGNING")))
1235   (if (and (epg-data-string plain)
1236            (eq (process-status (epg-context-process context)) 'run))
1237       (process-send-string (epg-context-process context)
1238                            (epg-data-string plain))))
1239
1240 ;;;###autoload
1241 (defun epg-sign-file (context plain signature &optional mode)
1242   "Sign a file PLAIN and store the result to a file SIGNATURE.
1243 If SIGNATURE is nil, it returns the result as a string.
1244 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
1245 If MODE is t or 'detached, it makes a detached signature.
1246 Otherwise, it makes a normal signature."
1247   (unwind-protect
1248       (progn
1249         (if signature
1250             (epg-context-set-output-file context signature)
1251           (epg-context-set-output-file context
1252                                        (epg-make-temp-file "epg-output")))
1253         (epg-start-sign context (epg-make-data-from-file plain) mode)
1254         (epg-wait-for-completion context)
1255         (if (epg-context-result-for context 'sign)
1256             (if (epg-context-result-for context 'error)
1257                 (message "Sign warning: %S"
1258                          (epg-context-result-for context 'error)))
1259           (if (epg-context-result-for context 'error)
1260               (error "Sign failed: %S"
1261                      (epg-context-result-for context 'error))
1262             (error "Sign failed")))
1263         (unless signature
1264           (epg-read-output context)))
1265     (unless signature
1266       (epg-delete-output-file context))
1267     (epg-reset context)))
1268
1269 ;;;###autoload
1270 (defun epg-sign-string (context plain &optional mode)
1271   "Sign a string PLAIN and return the output as string.
1272 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
1273 If MODE is t or 'detached, it makes a detached signature.
1274 Otherwise, it makes a normal signature."
1275   (unwind-protect
1276       (progn
1277         (epg-context-set-output-file context
1278                                      (epg-make-temp-file "epg-output"))
1279         (epg-start-sign context (epg-make-data-from-string plain) mode)
1280         (epg-flush context)
1281         (epg-wait-for-completion context)
1282         (if (epg-context-result-for context 'sign)
1283             (if (epg-context-result-for context 'error)
1284                 (message "Sign warning: %S"
1285                          (epg-context-result-for context 'error)))
1286           (if (epg-context-result-for context 'error)
1287               (error "Sign failed: %S"
1288                      (epg-context-result-for context 'error))
1289             (error "Sign failed")))
1290         (epg-read-output context))
1291     (epg-delete-output-file context)
1292     (epg-reset context)))
1293
1294 ;;;###autoload
1295 (defun epg-start-encrypt (context plain recipients
1296                                   &optional sign always-trust)
1297   "Initiate an encrypt operation on PLAIN.
1298 PLAIN is a data object.
1299 If RECIPIENTS is nil, it performs symmetric encryption.
1300
1301 If you use this function, you will need to wait for the completion of
1302 `epg-gpg-program' by using `epg-wait-for-completion' and call
1303 `epg-reset' to clear a temporaly output file.
1304 If you are unsure, use synchronous version of this function
1305 `epg-encrypt-file' or `epg-encrypt-string' instead."
1306   (epg-context-set-result context nil)
1307   (epg-start context
1308              (append (if always-trust '("--always-trust"))
1309                      (if recipients '("--encrypt") '("--symmetric"))
1310                      (if sign
1311                          (cons "--sign"
1312                                (apply #'nconc
1313                                       (mapcar (lambda (signer)
1314                                                 (list "-u" signer))
1315                                               (epg-context-signers context)))))
1316                      (apply #'nconc
1317                             (mapcar
1318                              (lambda (recipient)
1319                                (list "-r"
1320                                      (epg-sub-key-id
1321                                       (car (epg-key-sub-key-list recipient)))))
1322                              recipients))
1323                      (if (epg-data-file plain)
1324                          (list (epg-data-file plain)))))
1325   ;; `gpgsm' does not read passphrase from stdin, so waiting is not needed.
1326   (unless (eq (epg-context-protocol context) 'CMS)
1327     (if sign
1328         (epg-wait-for-status context '("BEGIN_SIGNING"))
1329       (epg-wait-for-status context '("BEGIN_ENCRYPTION"))))
1330   (if (and (epg-data-string plain)
1331            (eq (process-status (epg-context-process context)) 'run))
1332       (process-send-string (epg-context-process context)
1333                            (epg-data-string plain))))
1334
1335 ;;;###autoload
1336 (defun epg-encrypt-file (context plain recipients
1337                                  cipher &optional sign always-trust)
1338   "Encrypt a file PLAIN and store the result to a file CIPHER.
1339 If CIPHER is nil, it returns the result as a string.
1340 If RECIPIENTS is nil, it performs symmetric encryption."
1341   (unwind-protect
1342       (progn
1343         (if cipher
1344             (epg-context-set-output-file context cipher)
1345           (epg-context-set-output-file context
1346                                        (epg-make-temp-file "epg-output")))
1347         (epg-start-encrypt context (epg-make-data-from-file plain)
1348                            recipients sign always-trust)
1349         (epg-wait-for-completion context)
1350         (if sign
1351             (if (epg-context-result-for context 'sign)
1352                 (if (epg-context-result-for context 'error)
1353                     (message "Sign warning: %S"
1354                              (epg-context-result-for context 'error)))
1355               (if (epg-context-result-for context 'error)
1356                   (error "Sign failed: %S"
1357                          (epg-context-result-for context 'error))
1358                 (error "Sign failed"))))
1359         (if (epg-context-result-for context 'error)
1360             (error "Encrypt failed: %S"
1361                    (epg-context-result-for context 'error)))
1362         (unless cipher
1363           (epg-read-output context)))
1364     (unless cipher
1365       (epg-delete-output-file context))
1366     (epg-reset context)))
1367
1368 ;;;###autoload
1369 (defun epg-encrypt-string (context plain recipients
1370                                    &optional sign always-trust)
1371   "Encrypt a string PLAIN.
1372 If RECIPIENTS is nil, it performs symmetric encryption."
1373   (unwind-protect
1374       (progn
1375         (epg-context-set-output-file context
1376                                      (epg-make-temp-file "epg-output"))
1377         (epg-start-encrypt context (epg-make-data-from-string plain)
1378                            recipients sign always-trust)
1379         (epg-flush context)
1380         (epg-wait-for-completion context)
1381         (if sign
1382             (if (epg-context-result-for context 'sign)
1383                 (if (epg-context-result-for context 'error)
1384                     (message "Sign warning: %S"
1385                              (epg-context-result-for context 'error)))
1386               (if (epg-context-result-for context 'error)
1387                   (error "Sign failed: %S"
1388                          (epg-context-result-for context 'error))
1389                 (error "Sign failed"))))
1390         (if (epg-context-result-for context 'error)
1391             (error "Encrypt failed: %S"
1392                    (epg-context-result-for context 'error)))
1393         (epg-read-output context))
1394     (epg-delete-output-file context)
1395     (epg-reset context)))
1396
1397 ;;;###autoload
1398 (defun epg-start-export-keys (context keys)
1399   "Initiate an export keys operation.
1400
1401 If you use this function, you will need to wait for the completion of
1402 `epg-gpg-program' by using `epg-wait-for-completion' and call
1403 `epg-reset' to clear a temporaly output file.
1404 If you are unsure, use synchronous version of this function
1405 `epg-export-keys-to-file' or `epg-export-keys-to-string' instead."
1406   (epg-context-set-result context nil)
1407   (epg-start context (cons "--export"
1408                            (mapcar
1409                             (lambda (key)
1410                               (epg-sub-key-id
1411                                (car (epg-key-sub-key-list key))))
1412                             keys))))
1413
1414 ;;;###autoload
1415 (defun epg-export-keys-to-file (context keys file)
1416   "Extract public KEYS."
1417   (unwind-protect
1418       (progn
1419         (if keys
1420             (epg-context-set-output-file context file)
1421           (epg-context-set-output-file context
1422                                        (epg-make-temp-file "epg-output")))
1423         (epg-start-export-keys context keys)
1424         (epg-wait-for-completion context)
1425         (if (epg-context-result-for context 'error)
1426             (error "Export keys failed: %S"
1427                    (epg-context-result-for context 'error)))
1428         (unless file
1429           (epg-read-output context)))
1430     (unless file
1431       (epg-delete-output-file context))
1432     (epg-reset context)))
1433
1434 ;;;###autoload
1435 (defun epg-export-keys-to-string (context keys)
1436   "Extract public KEYS and return them as a string."
1437   (epg-export-keys-to-file context keys nil))
1438
1439 ;;;###autoload
1440 (defun epg-start-import-keys (context keys)
1441   "Initiate an import keys operation.
1442 KEYS is a data object.
1443
1444 If you use this function, you will need to wait for the completion of
1445 `epg-gpg-program' by using `epg-wait-for-completion' and call
1446 `epg-reset' to clear a temporaly output file.
1447 If you are unsure, use synchronous version of this function
1448 `epg-import-keys-from-file' or `epg-import-keys-from-string' instead."
1449   (epg-context-set-result context nil)
1450   (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
1451   (epg-start context (list "--import" (epg-data-file keys)))
1452   (if (and (epg-data-string keys)
1453            (eq (process-status (epg-context-process context)) 'run))
1454       (process-send-string (epg-context-process context)
1455                            (epg-data-string keys))))
1456   
1457 (defun epg-import-keys-1 (context keys)
1458   (unwind-protect
1459       (progn
1460         (epg-start-import-keys context keys)
1461         (if (epg-data-file keys)
1462             (epg-flush context))
1463         (epg-wait-for-completion context)
1464         (if (epg-context-result-for context 'error)
1465             (error "Import keys failed: %S"
1466                    (epg-context-result-for context 'error)))
1467         (epg-read-output context))
1468     (epg-reset context)))
1469
1470 ;;;###autoload
1471 (defun epg-import-keys-from-file (context keys)
1472   "Add keys from a file KEYS."
1473   (epg-import-keys-1 context (epg-make-data-from-file keys)))
1474
1475 ;;;###autoload
1476 (defun epg-import-keys-from-string (context keys)
1477   "Add keys from a string KEYS."
1478   (epg-import-keys-1 context (epg-make-data-from-string keys)))
1479
1480 ;;;###autoload
1481 (defun epg-start-delete-keys (context keys &optional allow-secret)
1482   "Initiate an delete keys operation.
1483
1484 If you use this function, you will need to wait for the completion of
1485 `epg-gpg-program' by using `epg-wait-for-completion' and call
1486 `epg-reset' to clear a temporaly output file.
1487 If you are unsure, use synchronous version of this function
1488 `epg-delete-keys' instead."
1489   (epg-context-set-result context nil)
1490   (epg-start context (cons (if allow-secret
1491                                "--delete-secret-key"
1492                              "--delete-key")
1493                            (mapcar
1494                             (lambda (key)
1495                               (epg-sub-key-id
1496                                (car (epg-key-sub-key-list key))))
1497                             keys))))
1498
1499 ;;;###autoload
1500 (defun epg-delete-keys (context keys &optional allow-secret)
1501   "Delete KEYS from the key ring."
1502   (unwind-protect
1503       (progn
1504         (epg-start-delete-keys context keys allow-secret)
1505         (epg-wait-for-completion context)
1506         (if (epg-context-result-for context 'error)
1507             (error "Delete keys failed: %S"
1508                    (epg-context-result-for context 'error))))
1509     (epg-reset context)))
1510
1511 ;;;###autoload
1512 (defun epg-start-sign-keys (context keys &optional local)
1513   "Initiate an sign keys operation.
1514
1515 If you use this function, you will need to wait for the completion of
1516 `epg-gpg-program' by using `epg-wait-for-completion' and call
1517 `epg-reset' to clear a temporaly output file.
1518 If you are unsure, use synchronous version of this function
1519 `epg-sign-keys' instead."
1520   (epg-context-set-result context nil)
1521   (epg-start context (cons (if local
1522                                "--lsign-key"
1523                              "--sign-key")
1524                            (mapcar
1525                             (lambda (key)
1526                               (epg-sub-key-id
1527                                (car (epg-key-sub-key-list key))))
1528                             keys))))
1529
1530 ;;;###autoload
1531 (defun epg-sign-keys (context keys &optional local)
1532   "Sign KEYS from the key ring."
1533   (unwind-protect
1534       (progn
1535         (epg-start-sign-keys context keys local)
1536         (epg-wait-for-completion context)
1537         (if (epg-context-result-for context 'error)
1538             (error "Sign keys failed: %S"
1539                    (epg-context-result-for context 'error))))
1540     (epg-reset context)))
1541
1542 (defun epg-decode-hexstring (string)
1543   (let ((index 0))
1544     (while (eq index (string-match "[0-9A-Fa-f][0-9A-Fa-f]" string index))
1545       (setq string (replace-match "\\x\\&" t nil string)
1546             index (+ index 4)))
1547     (car (read-from-string (concat "\"" string "\"")))))
1548
1549 (defun epg-decode-quotedstring (string)
1550   (let ((index 0))
1551     (while (string-match "\\\\\\(\\([,=+<>#;\\\"]\\)\\|\
1552 \\([0-9A-Fa-f][0-9A-Fa-f]\\)\\|\\(.\\)\\)"
1553                          string index)
1554       (if (match-beginning 2)
1555           (setq string (replace-match "\\2" t nil string)
1556                 index (1+ index))
1557         (if (match-beginning 3)
1558             (setq string (replace-match "\\x\\3" t nil string)
1559                   index (+ index 4))
1560           (setq string (replace-match "\\\\\\\\\\4" t nil string)
1561                 index (+ index 3)))))
1562     (car (read-from-string (concat "\"" string "\"")))))
1563
1564 (defun epg-dn-from-string (string)
1565   "Parse STRING as LADPv3 Distinguished Names (RFC2253).
1566 The return value is an alist mapping from types to values."
1567   (let ((index 0)
1568         (length (length string))
1569         alist type value group)
1570     (while (< index length)
1571       (if (eq index (string-match "[ \t\n\r]*" string index))
1572           (setq index (match-end 0)))
1573       (if (eq index (string-match
1574                      "\\([0-9]+\\(\\.[0-9]+\\)*\\)\[ \t\n\r]*=[ \t\n\r]*"
1575                      string index))
1576           (setq type (match-string 1 string)
1577                 index (match-end 0))
1578         (if (eq index (string-match "\\([0-9A-Za-z]+\\)[ \t\n\r]*=[ \t\n\r]*"
1579                                     string index))
1580             (setq type (match-string 1 string)
1581                   index (match-end 0))))
1582       (unless type
1583         (error "Invalid type"))
1584       (if (eq index (string-match
1585                      "\\([^,=+<>#;\\\"]\\|\\\\.\\)+"
1586                      string index))
1587           (setq index (match-end 0)
1588                 value (epg-decode-quotedstring (match-string 0 string)))
1589         (if (eq index (string-match "#\\([0-9A-Fa-f]+\\)" string index))
1590             (setq index (match-end 0)
1591                   value (epg-decode-hexstring (match-string 1 string)))
1592           (if (eq index (string-match "\"\\([^\\\"]\\|\\\\.\\)*\""
1593                                       string index))
1594               (setq index (match-end 0)
1595                     value (epg-decode-quotedstring (match-string 0 string))))))
1596       (if group
1597           (if (stringp (car (car alist)))
1598               (setcar alist (list (cons type value) (car alist)))
1599             (setcar alist (cons (cons type value) (car alist))))
1600         (if (consp (car (car alist)))
1601             (setcar alist (nreverse (car alist))))
1602         (setq alist (cons (cons type value) alist)
1603               type nil
1604               value nil))
1605       (if (eq index (string-match "[ \t\n\r]*\\([,;+]\\)" string index))
1606           (setq index (match-end 0)
1607                 group (eq (aref string (match-beginning 1)) ?+))))
1608     (nreverse alist)))
1609
1610 (defun epg-decode-dn (alist)
1611   "Convert ALIST returned by `epg-dn-from-string' to a human readable form.
1612 Type names are resolved using `epg-dn-type-alist'."
1613   (mapconcat
1614    (lambda (rdn)
1615      (if (stringp (car rdn))
1616          (let ((entry (assoc (car rdn) epg-dn-type-alist)))
1617            (if entry
1618                (format "%s=%s" (cdr entry) (cdr rdn))
1619              (format "%s=%s" (car rdn) (cdr rdn))))
1620        (concat "(" (epg-decode-dn rdn) ")")))
1621    alist
1622    ", "))
1623
1624 (provide 'epg)
1625
1626 ;;; epg.el ends here