Check if process is running.
[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-key-id
611                          (if (consp (epg-context-passphrase-callback
612                                      epg-context))
613                              (cdr (epg-context-passphrase-callback
614                                    epg-context)))))
615                   (when passphrase
616                     (setq passphrase-with-new-line (concat passphrase "\n"))
617                     (fillarray passphrase 0)
618                     (setq passphrase nil)
619                     (process-send-string process passphrase-with-new-line)))
620               (quit
621                (epg-context-set-result-for
622                 epg-context 'error
623                 (cons 'quit
624                       (epg-context-result-for epg-context 'error)))
625                (delete-process process)))
626           (if passphrase
627               (fillarray passphrase 0))
628           (if passphrase-with-new-line
629               (fillarray passphrase-with-new-line 0))))))
630
631 (defun epg-status-GET_BOOL (process string)
632   (let ((entry (assoc string epg-prompt-alist))
633         inhibit-quit)
634     (condition-case nil
635       (if (y-or-n-p (if entry (cdr entry) (concat string "? ")))
636           (process-send-string process "y\n")
637         (process-send-string process "n\n"))
638       (quit
639        (epg-context-set-result-for
640         epg-context 'error
641         (cons 'quit
642               (epg-context-result-for epg-context 'error)))
643        (delete-process process)))))
644
645 (defun epg-status-GET_LINE (process string)
646   (let ((entry (assoc string epg-prompt-alist))
647         inhibit-quit)
648     (condition-case nil
649         (process-send-string
650          process
651          (concat (read-string (if entry (cdr entry) (concat string ": ")))
652                  "\n"))
653       (quit
654        (epg-context-set-result-for
655         epg-context 'error
656         (cons 'quit
657               (epg-context-result-for epg-context 'error)))
658        (delete-process process)))))
659
660 (defun epg-status-GOODSIG (process string)
661   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
662       (epg-context-set-result-for
663        epg-context
664        'verify
665        (cons (epg-make-signature
666               'good
667               (match-string 1 string)
668               (if (eq (epg-context-protocol epg-context) 'CMS)
669                   (condition-case nil
670                       (epg-dn-from-string (match-string 2 string))
671                     (error (match-string 2 string)))
672                 (match-string 2 string)))
673              (epg-context-result-for epg-context 'verify)))))
674
675 (defun epg-status-EXPSIG (process string)
676   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
677       (epg-context-set-result-for
678        epg-context
679        'verify
680        (cons (epg-make-signature
681               'expired
682               (match-string 1 string)
683               (if (eq (epg-context-protocol epg-context) 'CMS)
684                   (condition-case nil
685                       (epg-dn-from-string (match-string 2 string))
686                     (error (match-string 2 string)))
687                 (match-string 2 string)))
688              (epg-context-result-for epg-context 'verify)))))
689
690 (defun epg-status-EXPKEYSIG (process string)
691   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
692       (epg-context-set-result-for
693        epg-context
694        'verify
695        (cons (epg-make-signature
696               'expired-key
697               (match-string 1 string)
698               (if (eq (epg-context-protocol epg-context) 'CMS)
699                   (condition-case nil
700                       (epg-dn-from-string (match-string 2 string))
701                     (error (match-string 2 string)))
702                 (match-string 2 string)))
703              (epg-context-result-for epg-context 'verify)))))
704
705 (defun epg-status-REVKEYSIG (process string)
706   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
707       (epg-context-set-result-for
708        epg-context
709        'verify
710        (cons (epg-make-signature
711               'revoked-key
712               (match-string 1 string)
713               (if (eq (epg-context-protocol epg-context) 'CMS)
714                   (condition-case nil
715                       (epg-dn-from-string (match-string 2 string))
716                     (error (match-string 2 string)))
717                 (match-string 2 string)))
718              (epg-context-result-for epg-context 'verify)))))
719
720 (defun epg-status-BADSIG (process string)
721   (if (string-match "\\`\\([^ ]+\\) \\(.*\\)" string)
722       (epg-context-set-result-for
723        epg-context
724        'verify
725        (cons (epg-make-signature
726               'bad
727               (match-string 1 string)
728               (if (eq (epg-context-protocol epg-context) 'CMS)
729                   (condition-case nil
730                       (epg-dn-from-string (match-string 2 string))
731                     (error (match-string 2 string)))
732                 (match-string 2 string)))
733              (epg-context-result-for epg-context 'verify)))))
734
735 (defun epg-status-VALIDSIG (process string)
736   (let ((signature (car (epg-context-result-for epg-context 'verify))))
737     (if (and signature
738              (eq (epg-signature-status signature) 'good)
739              (string-match "\\`\\([^ ]+\\) " string))
740         (epg-signature-set-fingerprint signature (match-string 1 string)))))
741
742 (defun epg-status-TRUST_UNDEFINED (process string)
743   (let ((signature (car (epg-context-result-for epg-context 'verify))))
744     (if (and signature
745              (eq (epg-signature-status signature) 'good))
746         (epg-signature-set-validity signature 'undefined))))
747
748 (defun epg-status-TRUST_NEVER (process string)
749   (let ((signature (car (epg-context-result-for epg-context 'verify))))
750     (if (and signature
751              (eq (epg-signature-status signature) 'good))
752         (epg-signature-set-validity signature 'never))))
753
754 (defun epg-status-TRUST_MARGINAL (process string)
755   (let ((signature (car (epg-context-result-for epg-context 'verify))))
756     (if (and signature
757              (eq (epg-signature-status signature) 'marginal))
758         (epg-signature-set-validity signature 'marginal))))
759
760 (defun epg-status-TRUST_FULLY (process string)
761   (let ((signature (car (epg-context-result-for epg-context 'verify))))
762     (if (and signature
763              (eq (epg-signature-status signature) 'good))
764         (epg-signature-set-validity signature 'full))))
765
766 (defun epg-status-TRUST_ULTIMATE (process string)
767   (let ((signature (car (epg-context-result-for epg-context 'verify))))
768     (if (and signature
769              (eq (epg-signature-status signature) 'good))
770         (epg-signature-set-validity signature 'ultimate))))
771
772 (defun epg-status-PROGRESS (process string)
773   (if (string-match "\\`\\([^ ]+\\) \\([^ ]\\) \\([0-9]+\\) \\([0-9]+\\)"
774                     string)
775       (funcall (if (consp (epg-context-progress-callback epg-context))
776                    (car (epg-context-progress-callback epg-context))
777                  (epg-context-progress-callback epg-context))
778                (match-string 1 string)
779                (match-string 2 string)
780                (string-to-number (match-string 3 string))
781                (string-to-number (match-string 4 string))
782                (if (consp (epg-context-progress-callback epg-context))
783                    (cdr (epg-context-progress-callback epg-context))))))
784
785 (defun epg-status-DECRYPTION_FAILED (process string)
786   (epg-context-set-result-for
787    epg-context 'error
788    (cons 'decryption-failed
789          (epg-context-result-for epg-context 'error))))
790
791 (defun epg-status-NODATA (process string)
792   (epg-context-set-result-for
793    epg-context 'error
794    (cons (cons 'no-data (string-to-number string))
795          (epg-context-result-for epg-context 'error))))
796
797 (defun epg-status-UNEXPECTED (process string)
798   (epg-context-set-result-for
799    epg-context 'error
800    (cons (cons 'unexpected (string-to-number string))
801          (epg-context-result-for epg-context 'error))))
802
803 (defun epg-status-KEYEXPIRED (process string)
804   (epg-context-set-result-for
805    epg-context 'error
806    (cons (cons 'key-expired string)
807          (epg-context-result-for epg-context 'error))))
808
809 (defun epg-status-KEYREVOKED (process string)
810   (epg-context-set-result-for
811    epg-context 'error
812    (cons 'key-revoked
813          (epg-context-result-for epg-context 'error))))
814
815 (defun epg-status-BADARMOR (process string)
816   (epg-context-set-result-for
817    epg-context 'error
818    (cons 'bad-armor
819          (epg-context-result-for epg-context 'error))))
820
821 (defun epg-status-INV_RECP (process string)
822   (if (string-match "\\`\\([0-9]+\\) \\(.*\\)" string)
823       (epg-context-set-result-for
824        epg-context 'error
825        (cons (list 'invalid-recipient
826                    (string-to-number (match-string 1 string))
827                    (match-string 2 string))
828              (epg-context-result-for epg-context 'error)))))
829
830 (defun epg-status-NO_RECP (process string)
831   (epg-context-set-result-for
832    epg-context 'error
833    (cons 'no-recipients
834          (epg-context-result-for epg-context 'error))))
835
836 (defun epg-status-DELETE_PROBLEM (process string)
837   (if (string-match "\\`\\([0-9]+\\)" string)
838       (epg-context-set-result-for
839        epg-context 'error
840        (cons (cons 'delete-problem (string-to-number (match-string 1 string)))
841              (epg-context-result-for epg-context 'error)))))
842
843 (defun epg-status-SIG_CREATED (process string)
844   (if (string-match "\\`\\([DCS]\\) \\([0-9]+\\) \\([0-9]+\\) \
845 \\([0-9A-Fa-F][0-9A-Fa-F]\\) \\(.*\\) " string)
846       (epg-context-set-result-for
847        epg-context 'sign
848        (cons (list (cons 'type (string-to-char (match-string 1 string)))
849                    (cons 'pubkey-algorithm
850                          (string-to-number (match-string 2 string)))
851                    (cons 'digest-algorithm
852                          (string-to-number (match-string 3 string)))
853                    (cons 'class (string-to-number (match-string 4 string) 16))
854                    (cons 'creation-time (match-string 5 string))
855                    (cons 'fingerprint (substring string (match-end 0))))
856              (epg-context-result-for epg-context 'sign)))))
857
858 (defun epg-passphrase-callback-function (key-id handback)
859   (read-passwd
860    (if (eq key-id 'SYM)
861        "Passphrase for symmetric encryption: "
862      (if (eq key-id 'PIN)
863          "Passphrase for PIN: "
864        (let ((entry (assoc key-id epg-user-id-alist)))
865          (if entry
866              (format "Passphrase for %s %s: " key-id (cdr entry))
867            (format "Passphrase for %s: " key-id)))))))
868
869 (defun epg-progress-callback-function (what char current total handback)
870   (message "%s: %d%%/%d%%" what current total))
871
872 (defun epg-configuration ()
873   "Return a list of internal configuration parameters of `epg-gpg-program'."
874   (let (config type)
875     (with-temp-buffer
876       (apply #'call-process epg-gpg-program nil (list t nil) nil
877              '("--with-colons" "--list-config"))
878       (goto-char (point-min))
879       (while (re-search-forward "^cfg:\\([^:]+\\):\\(.*\\)" nil t)
880         (setq type (intern (match-string 1))
881               config (cons (cons type
882                                  (if (memq type
883                                            '(pubkey cipher digest compress))
884                                      (mapcar #'string-to-number
885                                              (delete "" (split-string
886                                                          (match-string 2)
887                                                          ";")))
888                                    (match-string 2)))
889                            config))))
890     config))
891
892 (defun epg-list-keys-1 (context name mode)
893   (let ((args (append (list "--with-colons" "--no-greeting" "--batch"
894                             "--with-fingerprint"
895                             "--with-fingerprint"
896                             (if mode "--list-secret-keys" "--list-keys"))
897                       (unless (eq (epg-context-protocol context) 'CMS)
898                         '("--fixed-list-mode"))
899                       (if name (list name))))
900         keys string field index)
901     (with-temp-buffer
902       (apply #'call-process
903              (if (eq (epg-context-protocol context) 'CMS)
904                  epg-gpgsm-program
905                epg-gpg-program)
906              nil (list t nil) nil args)
907       (goto-char (point-min))
908       (while (re-search-forward "^[a-z][a-z][a-z]:.*" nil t)
909         (setq keys (cons (make-vector 15 nil) keys)
910               string (match-string 0)
911               index 0
912               field 0)
913         (while (eq index
914                    (string-match "\\([^:]+\\)?:" string index))
915           (setq index (match-end 0))
916           (aset (car keys) field (match-string 1 string))
917           (setq field (1+ field))))
918       (nreverse keys))))
919
920 (defun epg-make-sub-key-1 (line)
921   (epg-make-sub-key
922    (if (aref line 1)
923        (cdr (assq (string-to-char (aref line 1)) epg-key-validity-alist)))
924    (delq nil
925          (mapcar (lambda (char) (cdr (assq char epg-key-capablity-alist)))
926                  (aref line 11)))
927    (member (aref line 0) '("sec" "ssb"))
928    (string-to-number (aref line 3))
929    (string-to-number (aref line 2))
930    (aref line 4)
931    (aref line 5)
932    (aref line 6)))
933
934 (defun epg-list-keys (context &optional name mode)
935   (let ((lines (epg-list-keys-1 context name mode))
936         keys cert)
937     (while lines
938       (cond
939        ((member (aref (car lines) 0) '("pub" "sec" "crt" "crs"))
940         (when (car keys)
941           (epg-key-set-sub-key-list
942            (car keys)
943            (nreverse (epg-key-sub-key-list (car keys))))
944           (epg-key-set-user-id-list
945            (car keys)
946            (nreverse (epg-key-user-id-list (car keys)))))
947         (setq cert (member (aref (car lines) 0) '("crt" "crs"))
948               keys (cons (epg-make-key
949                           (if (aref (car lines) 8)
950                               (cdr (assq (string-to-char (aref (car lines) 8))
951                                          epg-key-validity-alist))))
952                          keys))
953         (epg-key-set-sub-key-list
954          (car keys)
955          (cons (epg-make-sub-key-1 (car lines))
956                (epg-key-sub-key-list (car keys)))))
957        ((member (aref (car lines) 0) '("sub" "ssb"))
958         (epg-key-set-sub-key-list
959          (car keys)
960          (cons (epg-make-sub-key-1 (car lines))
961                (epg-key-sub-key-list (car keys)))))
962        ((equal (aref (car lines) 0) "uid")
963         (epg-key-set-user-id-list
964          (car keys)
965          (cons (epg-make-user-id
966                 (if (aref (car lines) 1)
967                     (cdr (assq (string-to-char (aref (car lines) 1))
968                                epg-key-validity-alist)))
969                 (if cert
970                     (condition-case nil
971                         (epg-dn-from-string (aref (car lines) 9))
972                       (error (aref (car lines) 9)))
973                   (aref (car lines) 9)))
974                (epg-key-user-id-list (car keys)))))
975        ((equal (aref (car lines) 0) "fpr")
976         (epg-sub-key-set-fingerprint (car (epg-key-sub-key-list (car keys)))
977                                      (aref (car lines) 9))))
978       (setq lines (cdr lines)))
979     (when (car keys)
980       (epg-key-set-sub-key-list
981        (car keys)
982        (nreverse (epg-key-sub-key-list (car keys))))
983       (epg-key-set-user-id-list
984        (car keys)
985        (nreverse (epg-key-user-id-list (car keys)))))
986     (nreverse keys)))
987
988 (if (fboundp 'make-temp-file)
989     (defalias 'epg-make-temp-file 'make-temp-file)
990   ;; stolen from poe.el.
991   (defun epg-make-temp-file (prefix)
992     "Create a temporary file.
993 The returned file name (created by appending some random characters at the end
994 of PREFIX, and expanding against `temporary-file-directory' if necessary),
995 is guaranteed to point to a newly created empty file.
996 You can then use `write-region' to write new data into the file."
997     (let (tempdir tempfile)
998       (unwind-protect
999           (let (file)
1000             ;; First, create a temporary directory.
1001             (while (condition-case ()
1002                        (progn
1003                          (setq tempdir (make-temp-name
1004                                         (concat
1005                                          (file-name-directory prefix)
1006                                          "DIR")))
1007                          ;; return nil or signal an error.
1008                          (make-directory tempdir))
1009                      ;; let's try again.
1010                      (file-already-exists t)))
1011             (set-file-modes tempdir 448)
1012             ;; Second, create a temporary file in the tempdir.
1013             ;; There *is* a race condition between `make-temp-name'
1014             ;; and `write-region', but we don't care it since we are
1015             ;; in a private directory now.
1016             (setq tempfile (make-temp-name (concat tempdir "/EMU")))
1017             (write-region "" nil tempfile nil 'silent)
1018             (set-file-modes tempfile 384)
1019             ;; Finally, make a hard-link from the tempfile.
1020             (while (condition-case ()
1021                        (progn
1022                          (setq file (make-temp-name prefix))
1023                          ;; return nil or signal an error.
1024                          (add-name-to-file tempfile file))
1025                      ;; let's try again.
1026                      (file-already-exists t)))
1027             file)
1028         ;; Cleanup the tempfile.
1029         (and tempfile
1030              (file-exists-p tempfile)
1031              (delete-file tempfile))
1032         ;; Cleanup the tempdir.
1033         (and tempdir
1034              (file-directory-p tempdir)
1035              (delete-directory tempdir))))))
1036
1037 ;;;###autoload
1038 (defun epg-cancel (context)
1039   (if (eq (process-status (epg-context-process context)) 'run)
1040       (delete-process (epg-context-process context))))
1041   
1042 ;;;###autoload
1043 (defun epg-start-decrypt (context cipher)
1044   "Initiate a decrypt operation on CIPHER.
1045 CIPHER is a data object.
1046
1047 If you use this function, you will need to wait for the completion of
1048 `epg-gpg-program' by using `epg-wait-for-completion' and call
1049 `epg-reset' to clear a temporaly output file.
1050 If you are unsure, use synchronous version of this function
1051 `epg-decrypt-file' or `epg-decrypt-string' instead."
1052   (unless (epg-data-file cipher)
1053     (error "Not a file"))
1054   (epg-context-set-result context nil)
1055   (epg-start context (list "--decrypt" (epg-data-file cipher)))
1056   ;; `gpgsm' does not read passphrase from stdin, so waiting is not needed.
1057   (unless (eq (epg-context-protocol context) 'CMS)
1058     (epg-wait-for-status context '("BEGIN_DECRYPTION"))))
1059
1060 ;;;###autoload
1061 (defun epg-decrypt-file (context cipher plain)
1062   "Decrypt a file CIPHER and store the result to a file PLAIN.
1063 If PLAIN is nil, it returns the result as a string."
1064   (unwind-protect
1065       (progn
1066         (if plain
1067             (epg-context-set-output-file context plain)
1068           (epg-context-set-output-file context
1069                                        (epg-make-temp-file "epg-output")))
1070         (epg-start-decrypt context (epg-make-data-from-file cipher))
1071         (epg-wait-for-completion context)
1072         (if (epg-context-result-for context 'error)
1073             (error "Decrypt failed: %S"
1074                    (epg-context-result-for context 'error)))
1075         (unless plain
1076           (epg-read-output context)))
1077     (unless plain
1078       (epg-delete-output-file context))
1079     (epg-reset context)))
1080
1081 ;;;###autoload
1082 (defun epg-decrypt-string (context cipher)
1083   "Decrypt a string CIPHER and return the plain text."
1084   (let ((input-file (epg-make-temp-file "epg-input"))
1085         (coding-system-for-write 'binary))
1086     (unwind-protect
1087         (progn
1088           (write-region cipher nil input-file nil 'quiet)
1089           (epg-context-set-output-file context
1090                                        (epg-make-temp-file "epg-output"))
1091           (epg-start-decrypt context (epg-make-data-from-file input-file))
1092           (epg-flush context)
1093           (epg-wait-for-completion context)
1094           (if (epg-context-result-for context 'error)
1095               (error "Decrypt failed: %S"
1096                      (epg-context-result-for context 'error)))
1097           (epg-read-output context))
1098       (epg-delete-output-file context)
1099       (if (file-exists-p input-file)
1100           (delete-file input-file))
1101       (epg-reset context))))
1102
1103 ;;;###autoload
1104 (defun epg-start-verify (context signature &optional signed-text)
1105   "Initiate a verify operation on SIGNATURE.
1106 SIGNATURE and SIGNED-TEXT are a data object if they are specified.
1107
1108 For a detached signature, both SIGNATURE and SIGNED-TEXT should be set.
1109 For a normal or a clear text signature, SIGNED-TEXT should be nil.
1110
1111 If you use this function, you will need to wait for the completion of
1112 `epg-gpg-program' by using `epg-wait-for-completion' and call
1113 `epg-reset' to clear a temporaly output file.
1114 If you are unsure, use synchronous version of this function
1115 `epg-verify-file' or `epg-verify-string' instead."
1116   (epg-context-set-result context nil)
1117   (if signed-text
1118       ;; Detached signature.
1119       (if (epg-data-file signed-text)
1120           (epg-start context (list "--verify" (epg-data-file signature)
1121                                    (epg-data-file signed-text)))
1122         (epg-start context (list "--verify" (epg-data-file signature) "-"))
1123         (if (eq (process-status (epg-context-process context)) 'run)
1124             (process-send-string (epg-context-process context)
1125                                  (epg-data-string signed-text))))
1126     ;; Normal (or cleartext) signature.
1127     (if (epg-data-file signature)
1128         (epg-start context (list "--verify" (epg-data-file signature)))
1129       (epg-start context (list "--verify"))
1130       (if (eq (process-status (epg-context-process context)) 'run)
1131           (process-send-string (epg-context-process context)
1132                                (epg-data-string signature))))))
1133
1134 ;;;###autoload
1135 (defun epg-verify-file (context signature &optional signed-text plain)
1136   "Verify a file SIGNATURE.
1137 SIGNED-TEXT and PLAIN are also a file if they are specified.
1138
1139 For a detached signature, both SIGNATURE and SIGNED-TEXT should be string.
1140 For a normal or a clear text signature, SIGNED-TEXT should be nil."
1141   (unwind-protect
1142       (progn
1143         (if plain
1144             (epg-context-set-output-file context plain)
1145           (epg-context-set-output-file context
1146                                        (epg-make-temp-file "epg-output")))
1147         (if signed-text
1148             (epg-start-verify context
1149                               (epg-make-data-from-file signature)
1150                               (epg-make-data-from-file signed-text))
1151           (epg-start-verify context
1152                             (epg-make-data-from-file signature)))
1153         (epg-wait-for-completion context)
1154         (unless plain
1155           (epg-read-output context)))
1156     (unless plain
1157       (epg-delete-output-file context))
1158     (epg-reset context)))
1159
1160 ;;;###autoload
1161 (defun epg-verify-string (context signature &optional signed-text)
1162   "Verify a string SIGNATURE.
1163 SIGNED-TEXT is a string if it is specified.
1164
1165 For a detached signature, both SIGNATURE and SIGNED-TEXT should be string.
1166 For a normal or a clear text signature, SIGNED-TEXT should be nil."
1167   (let ((coding-system-for-write 'binary)
1168         input-file)
1169     (unwind-protect
1170         (progn
1171           (epg-context-set-output-file context
1172                                        (epg-make-temp-file "epg-output"))
1173           (if signed-text
1174               (progn
1175                 (setq input-file (epg-make-temp-file "epg-signature"))
1176                 (write-region signature nil input-file nil 'quiet)
1177                 (epg-start-verify context
1178                                   (epg-make-data-from-file input-file)
1179                                   (epg-make-data-from-string signed-text)))
1180             (epg-start-verify context (epg-make-data-from-string signature)))
1181           (epg-flush context)
1182           (epg-wait-for-completion context)
1183           (epg-read-output context))
1184       (epg-delete-output-file context)
1185       (if (and input-file
1186                (file-exists-p input-file))
1187           (delete-file input-file))
1188       (epg-reset context))))
1189
1190 ;;;###autoload
1191 (defun epg-start-sign (context plain &optional mode)
1192   "Initiate a sign operation on PLAIN.
1193 PLAIN is a data object.
1194
1195 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
1196 If MODE is t or 'detached, it makes a detached signature.
1197 Otherwise, it makes a normal signature.
1198
1199 If you use this function, you will need to wait for the completion of
1200 `epg-gpg-program' by using `epg-wait-for-completion' and call
1201 `epg-reset' to clear a temporaly output file.
1202 If you are unsure, use synchronous version of this function
1203 `epg-sign-file' or `epg-sign-string' instead."
1204   (epg-context-set-result context nil)
1205   (epg-start context
1206              (append (list (if (eq mode 'clearsign)
1207                                "--clearsign"
1208                              (if (or (eq mode t) (eq mode 'detached))
1209                                  "--detach-sign"
1210                                "--sign")))
1211                      (apply #'nconc
1212                             (mapcar
1213                              (lambda (signer)
1214                                (list "-u"
1215                                      (epg-sub-key-id
1216                                       (car (epg-key-sub-key-list signer)))))
1217                              (epg-context-signers context)))
1218                      (if (epg-data-file plain)
1219                          (list (epg-data-file plain)))))
1220   ;; `gpgsm' does not read passphrase from stdin, so waiting is not needed.
1221   (unless (eq (epg-context-protocol context) 'CMS)
1222     (epg-wait-for-status context '("BEGIN_SIGNING")))
1223   (if (and (epg-data-string plain)
1224            (eq (process-status (epg-context-process context)) 'run))
1225       (process-send-string (epg-context-process context)
1226                            (epg-data-string plain))))
1227
1228 ;;;###autoload
1229 (defun epg-sign-file (context plain signature &optional mode)
1230   "Sign a file PLAIN and store the result to a file SIGNATURE.
1231 If SIGNATURE is nil, it returns the result as a string.
1232 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
1233 If MODE is t or 'detached, it makes a detached signature.
1234 Otherwise, it makes a normal signature."
1235   (unwind-protect
1236       (progn
1237         (if signature
1238             (epg-context-set-output-file context signature)
1239           (epg-context-set-output-file context
1240                                        (epg-make-temp-file "epg-output")))
1241         (epg-start-sign context (epg-make-data-from-file plain) mode)
1242         (epg-wait-for-completion context)
1243         (if (epg-context-result-for context 'sign)
1244             (if (epg-context-result-for context 'error)
1245                 (message "Sign warning: %S"
1246                          (epg-context-result-for context 'error)))
1247           (if (epg-context-result-for context 'error)
1248               (error "Sign failed: %S"
1249                      (epg-context-result-for context 'error))
1250             (error "Sign failed")))
1251         (unless signature
1252           (epg-read-output context)))
1253     (unless signature
1254       (epg-delete-output-file context))
1255     (epg-reset context)))
1256
1257 ;;;###autoload
1258 (defun epg-sign-string (context plain &optional mode)
1259   "Sign a string PLAIN and return the output as string.
1260 If optional 3rd argument MODE is 'clearsign, it makes a clear text signature.
1261 If MODE is t or 'detached, it makes a detached signature.
1262 Otherwise, it makes a normal signature."
1263   (unwind-protect
1264       (progn
1265         (epg-context-set-output-file context
1266                                      (epg-make-temp-file "epg-output"))
1267         (epg-start-sign context (epg-make-data-from-string plain) mode)
1268         (epg-flush context)
1269         (epg-wait-for-completion context)
1270         (if (epg-context-result-for context 'sign)
1271             (if (epg-context-result-for context 'error)
1272                 (message "Sign warning: %S"
1273                          (epg-context-result-for context 'error)))
1274           (if (epg-context-result-for context 'error)
1275               (error "Sign failed: %S"
1276                      (epg-context-result-for context 'error))
1277             (error "Sign failed")))
1278         (epg-read-output context))
1279     (epg-delete-output-file context)
1280     (epg-reset context)))
1281
1282 ;;;###autoload
1283 (defun epg-start-encrypt (context plain recipients
1284                                   &optional sign always-trust)
1285   "Initiate an encrypt operation on PLAIN.
1286 PLAIN is a data object.
1287 If RECIPIENTS is nil, it performs symmetric encryption.
1288
1289 If you use this function, you will need to wait for the completion of
1290 `epg-gpg-program' by using `epg-wait-for-completion' and call
1291 `epg-reset' to clear a temporaly output file.
1292 If you are unsure, use synchronous version of this function
1293 `epg-encrypt-file' or `epg-encrypt-string' instead."
1294   (epg-context-set-result context nil)
1295   (epg-start context
1296              (append (if always-trust '("--always-trust"))
1297                      (if recipients '("--encrypt") '("--symmetric"))
1298                      (if sign
1299                          (cons "--sign"
1300                                (apply #'nconc
1301                                       (mapcar (lambda (signer)
1302                                                 (list "-u" signer))
1303                                               (epg-context-signers context)))))
1304                      (apply #'nconc
1305                             (mapcar
1306                              (lambda (recipient)
1307                                (list "-r"
1308                                      (epg-sub-key-id
1309                                       (car (epg-key-sub-key-list recipient)))))
1310                              recipients))
1311                      (if (epg-data-file plain)
1312                          (list (epg-data-file plain)))))
1313   ;; `gpgsm' does not read passphrase from stdin, so waiting is not needed.
1314   (unless (eq (epg-context-protocol context) 'CMS)
1315     (if sign
1316         (epg-wait-for-status context '("BEGIN_SIGNING"))
1317       (epg-wait-for-status context '("BEGIN_ENCRYPTION"))))
1318   (if (and (epg-data-string plain)
1319            (eq (process-status (epg-context-process context)) 'run))
1320       (process-send-string (epg-context-process context)
1321                            (epg-data-string plain))))
1322
1323 ;;;###autoload
1324 (defun epg-encrypt-file (context plain recipients
1325                                  cipher &optional sign always-trust)
1326   "Encrypt a file PLAIN and store the result to a file CIPHER.
1327 If CIPHER is nil, it returns the result as a string.
1328 If RECIPIENTS is nil, it performs symmetric encryption."
1329   (unwind-protect
1330       (progn
1331         (if cipher
1332             (epg-context-set-output-file context cipher)
1333           (epg-context-set-output-file context
1334                                        (epg-make-temp-file "epg-output")))
1335         (epg-start-encrypt context (epg-make-data-from-file plain)
1336                            recipients sign always-trust)
1337         (epg-wait-for-completion context)
1338         (if sign
1339             (if (epg-context-result-for context 'sign)
1340                 (if (epg-context-result-for context 'error)
1341                     (message "Sign warning: %S"
1342                              (epg-context-result-for context 'error)))
1343               (if (epg-context-result-for context 'error)
1344                   (error "Sign failed: %S"
1345                          (epg-context-result-for context 'error))
1346                 (error "Sign failed"))))
1347         (if (epg-context-result-for context 'error)
1348             (error "Encrypt failed: %S"
1349                    (epg-context-result-for context 'error)))
1350         (unless cipher
1351           (epg-read-output context)))
1352     (unless cipher
1353       (epg-delete-output-file context))
1354     (epg-reset context)))
1355
1356 ;;;###autoload
1357 (defun epg-encrypt-string (context plain recipients
1358                                    &optional sign always-trust)
1359   "Encrypt a string PLAIN.
1360 If RECIPIENTS is nil, it performs symmetric encryption."
1361   (unwind-protect
1362       (progn
1363         (epg-context-set-output-file context
1364                                      (epg-make-temp-file "epg-output"))
1365         (epg-start-encrypt context (epg-make-data-from-string plain)
1366                            recipients sign always-trust)
1367         (epg-flush context)
1368         (epg-wait-for-completion context)
1369         (if sign
1370             (if (epg-context-result-for context 'sign)
1371                 (if (epg-context-result-for context 'error)
1372                     (message "Sign warning: %S"
1373                              (epg-context-result-for context 'error)))
1374               (if (epg-context-result-for context 'error)
1375                   (error "Sign failed: %S"
1376                          (epg-context-result-for context 'error))
1377                 (error "Sign failed"))))
1378         (if (epg-context-result-for context 'error)
1379             (error "Encrypt failed: %S"
1380                    (epg-context-result-for context 'error)))
1381         (epg-read-output context))
1382     (epg-delete-output-file context)
1383     (epg-reset context)))
1384
1385 ;;;###autoload
1386 (defun epg-start-export-keys (context keys)
1387   "Initiate an export keys operation.
1388
1389 If you use this function, you will need to wait for the completion of
1390 `epg-gpg-program' by using `epg-wait-for-completion' and call
1391 `epg-reset' to clear a temporaly output file.
1392 If you are unsure, use synchronous version of this function
1393 `epg-export-keys-to-file' or `epg-export-keys-to-string' instead."
1394   (epg-context-set-result context nil)
1395   (epg-start context (cons "--export"
1396                            (mapcar
1397                             (lambda (key)
1398                               (epg-sub-key-id
1399                                (car (epg-key-sub-key-list key))))
1400                             keys))))
1401
1402 ;;;###autoload
1403 (defun epg-export-keys-to-file (context keys file)
1404   "Extract public KEYS."
1405   (unwind-protect
1406       (progn
1407         (if keys
1408             (epg-context-set-output-file context file)
1409           (epg-context-set-output-file context
1410                                        (epg-make-temp-file "epg-output")))
1411         (epg-start-export-keys context keys)
1412         (epg-wait-for-completion context)
1413         (if (epg-context-result-for context 'error)
1414             (error "Export keys failed: %S"
1415                    (epg-context-result-for context 'error)))
1416         (unless file
1417           (epg-read-output context)))
1418     (unless file
1419       (epg-delete-output-file context))
1420     (epg-reset context)))
1421
1422 ;;;###autoload
1423 (defun epg-export-keys-to-string (context keys)
1424   "Extract public KEYS and return them as a string."
1425   (epg-export-keys-to-file context keys nil))
1426
1427 ;;;###autoload
1428 (defun epg-start-import-keys (context keys)
1429   "Initiate an import keys operation.
1430 KEYS is a data object.
1431
1432 If you use this function, you will need to wait for the completion of
1433 `epg-gpg-program' by using `epg-wait-for-completion' and call
1434 `epg-reset' to clear a temporaly output file.
1435 If you are unsure, use synchronous version of this function
1436 `epg-import-keys-from-file' or `epg-import-keys-from-string' instead."
1437   (epg-context-set-result context nil)
1438   (epg-context-set-output-file context (epg-make-temp-file "epg-output"))
1439   (epg-start context (list "--import" (epg-data-file keys)))
1440   (if (and (epg-data-string keys)
1441            (eq (process-status (epg-context-process context)) 'run))
1442       (process-send-string (epg-context-process context)
1443                            (epg-data-string keys))))
1444   
1445 (defun epg-import-keys-1 (context keys)
1446   (unwind-protect
1447       (progn
1448         (epg-start-import-keys context keys)
1449         (if (epg-data-file keys)
1450             (epg-flush context))
1451         (epg-wait-for-completion context)
1452         (if (epg-context-result-for context 'error)
1453             (error "Import keys failed: %S"
1454                    (epg-context-result-for context 'error)))
1455         (epg-read-output context))
1456     (epg-reset context)))
1457
1458 ;;;###autoload
1459 (defun epg-import-keys-from-file (context keys)
1460   "Add keys from a file KEYS."
1461   (epg-import-keys-1 context (epg-make-data-from-file keys)))
1462
1463 ;;;###autoload
1464 (defun epg-import-keys-from-string (context keys)
1465   "Add keys from a string KEYS."
1466   (epg-import-keys-1 context (epg-make-data-from-string keys)))
1467
1468 ;;;###autoload
1469 (defun epg-start-delete-keys (context keys &optional allow-secret)
1470   "Initiate an delete keys operation.
1471
1472 If you use this function, you will need to wait for the completion of
1473 `epg-gpg-program' by using `epg-wait-for-completion' and call
1474 `epg-reset' to clear a temporaly output file.
1475 If you are unsure, use synchronous version of this function
1476 `epg-delete-keys' instead."
1477   (epg-context-set-result context nil)
1478   (epg-start context (cons (if allow-secret
1479                                "--delete-secret-key"
1480                              "--delete-key")
1481                            (mapcar
1482                             (lambda (key)
1483                               (epg-sub-key-id
1484                                (car (epg-key-sub-key-list key))))
1485                             keys))))
1486
1487 ;;;###autoload
1488 (defun epg-delete-keys (context keys &optional allow-secret)
1489   "Delete KEYS from the key ring."
1490   (unwind-protect
1491       (progn
1492         (epg-start-delete-keys context keys allow-secret)
1493         (epg-wait-for-completion context)
1494         (if (epg-context-result-for context 'error)
1495             (error "Delete keys failed: %S"
1496                    (epg-context-result-for context 'error))))
1497     (epg-reset context)))
1498
1499 ;;;###autoload
1500 (defun epg-start-sign-keys (context keys &optional local)
1501   "Initiate an sign keys operation.
1502
1503 If you use this function, you will need to wait for the completion of
1504 `epg-gpg-program' by using `epg-wait-for-completion' and call
1505 `epg-reset' to clear a temporaly output file.
1506 If you are unsure, use synchronous version of this function
1507 `epg-sign-keys' instead."
1508   (epg-context-set-result context nil)
1509   (epg-start context (cons (if local
1510                                "--lsign-key"
1511                              "--sign-key")
1512                            (mapcar
1513                             (lambda (key)
1514                               (epg-sub-key-id
1515                                (car (epg-key-sub-key-list key))))
1516                             keys))))
1517
1518 ;;;###autoload
1519 (defun epg-sign-keys (context keys &optional local)
1520   "Sign KEYS from the key ring."
1521   (unwind-protect
1522       (progn
1523         (epg-start-sign-keys context keys local)
1524         (epg-wait-for-completion context)
1525         (if (epg-context-result-for context 'error)
1526             (error "Sign keys failed: %S"
1527                    (epg-context-result-for context 'error))))
1528     (epg-reset context)))
1529
1530 (defun epg-decode-hexstring (string)
1531   (let ((index 0))
1532     (while (eq index (string-match "[0-9A-Fa-f][0-9A-Fa-f]" string index))
1533       (setq string (replace-match "\\x\\&" t nil string)
1534             index (+ index 4)))
1535     (car (read-from-string (concat "\"" string "\"")))))
1536
1537 (defun epg-decode-quotedstring (string)
1538   (let ((index 0))
1539     (while (string-match "\\\\\\(\\([,=+<>#;\\\"]\\)\\|\
1540 \\([0-9A-Fa-f][0-9A-Fa-f]\\)\\|\\(.\\)\\)"
1541                          string index)
1542       (if (match-beginning 2)
1543           (setq string (replace-match "\\2" t nil string)
1544                 index (1+ index))
1545         (if (match-beginning 3)
1546             (setq string (replace-match "\\x\\3" t nil string)
1547                   index (+ index 4))
1548           (setq string (replace-match "\\\\\\\\\\4" t nil string)
1549                 index (+ index 3)))))
1550     (car (read-from-string (concat "\"" string "\"")))))
1551
1552 (defun epg-dn-from-string (string)
1553   "Parse STRING as LADPv3 Distinguished Names (RFC2253).
1554 The return value is an alist mapping from types to values."
1555   (let ((index 0)
1556         (length (length string))
1557         alist type value group)
1558     (while (< index length)
1559       (if (eq index (string-match "[ \t\n\r]*" string index))
1560           (setq index (match-end 0)))
1561       (if (eq index (string-match
1562                      "\\([0-9]+\\(\\.[0-9]+\\)*\\)\[ \t\n\r]*=[ \t\n\r]*"
1563                      string index))
1564           (setq type (match-string 1 string)
1565                 index (match-end 0))
1566         (if (eq index (string-match "\\([0-9A-Za-z]+\\)[ \t\n\r]*=[ \t\n\r]*"
1567                                     string index))
1568             (setq type (match-string 1 string)
1569                   index (match-end 0))))
1570       (unless type
1571         (error "Invalid type"))
1572       (if (eq index (string-match
1573                      "\\([^,=+<>#;\\\"]\\|\\\\.\\)+"
1574                      string index))
1575           (setq index (match-end 0)
1576                 value (epg-decode-quotedstring (match-string 0 string)))
1577         (if (eq index (string-match "#\\([0-9A-Fa-f]+\\)" string index))
1578             (setq index (match-end 0)
1579                   value (epg-decode-hexstring (match-string 1 string)))
1580           (if (eq index (string-match "\"\\([^\\\"]\\|\\\\.\\)*\""
1581                                       string index))
1582               (setq index (match-end 0)
1583                     value (epg-decode-quotedstring (match-string 0 string))))))
1584       (if group
1585           (if (stringp (car (car alist)))
1586               (setcar alist (list (cons type value) (car alist)))
1587             (setcar alist (cons (cons type value) (car alist))))
1588         (if (consp (car (car alist)))
1589             (setcar alist (nreverse (car alist))))
1590         (setq alist (cons (cons type value) alist)
1591               type nil
1592               value nil))
1593       (if (eq index (string-match "[ \t\n\r]*\\([,;+]\\)" string index))
1594           (setq index (match-end 0)
1595                 group (eq (aref string (match-beginning 1)) ?+))))
1596     (nreverse alist)))
1597
1598 (defun epg-decode-dn (alist)
1599   "Convert ALIST returned by `epg-dn-from-string' to a human readable form.
1600 Type names are resolved using `epg-dn-type-alist'."
1601   (mapconcat
1602    (lambda (rdn)
1603      (if (stringp (car rdn))
1604          (let ((entry (assoc (car rdn) epg-dn-type-alist)))
1605            (if entry
1606                (format "%s=%s" (cdr entry) (cdr rdn))
1607              (format "%s=%s" (car rdn) (cdr rdn))))
1608        (concat "(" (epg-decode-dn rdn) ")")))
1609    alist
1610    ", "))
1611
1612 (provide 'epg)
1613
1614 ;;; epg.el ends here