]> code.delx.au - gnu-emacs/blobdiff - lisp/epg-config.el
* lisp/descr-text.el (describe-char-unicode-data): Fix copy/paste errors.
[gnu-emacs] / lisp / epg-config.el
index 2dbef64ecf95aca5b5aed2f0bca99c2b7ff79efe..9179e04dcc1ee85cd9aad019ff9fe7f210eaba09 100644 (file)
@@ -1,6 +1,6 @@
 ;;; epg-config.el --- configuration of the EasyPG Library
 
-;; Copyright (C) 2006-2013 Free Software Foundation, Inc.
+;; Copyright (C) 2006-2016 Free Software Foundation, Inc.
 
 ;; Author: Daiki Ueno <ueno@unixuser.org>
 ;; Keywords: PGP, GnuPG
@@ -23,6 +23,8 @@
 
 ;;; Code:
 
+(eval-when-compile (require 'cl-lib))
+
 (defconst epg-package-name "epg"
   "Name of this package.")
 
   :group 'data
   :group 'external)
 
-(defcustom epg-gpg-program (or (executable-find "gpg")
-                              (executable-find "gpg2")
-                              "gpg")
+(defcustom epg-gpg-program (if (executable-find "gpg2")
+                               "gpg2"
+                             "gpg")
   "The `gpg' executable."
+  :version "25.1"
   :group 'epg
   :type 'string)
 
   :group 'epg
   :type 'string)
 
+(defcustom epg-gpgconf-program "gpgconf"
+  "The `gpgconf' executable."
+  :version "25.1"
+  :group 'epg
+  :type 'string)
+
 (defcustom epg-gpg-home-directory nil
   "The directory which contains the configuration files of `epg-gpg-program'."
   :group 'epg
@@ -69,12 +78,78 @@ Note that the buffer name starts with a space."
 
 (defconst epg-gpg-minimum-version "1.4.3")
 
+(defconst epg-config--program-alist
+  '((OpenPGP
+     epg-gpg-program
+     ("gpg2" . "2.1.6") ("gpg" . "1.4.3"))
+    (CMS
+     epg-gpgsm-program
+     ("gpgsm" . "2.0.4")))
+  "Alist used to obtain the usable configuration of executables.
+The first element of each entry is protocol symbol, which is
+either `OpenPGP' or `CMS'.  The second element is a symbol where
+the executable name is remembered.  The rest of the entry is an
+alist mapping executable names to the minimum required version
+suitable for the use with Emacs.")
+
+(defconst epg-config--configuration-constructor-alist
+  '((OpenPGP . epg-config--make-gpg-configuration)
+    (CMS . epg-config--make-gpgsm-configuration))
+  "Alist used to obtain the usable configuration of executables.
+The first element of each entry is protocol symbol, which is
+either `OpenPGP' or `CMS'.  The second element is a function
+which constructs a configuration object (actually a plist).")
+
+(defvar epg--configurations nil)
+
 ;;;###autoload
-(defun epg-configuration ()
-  "Return a list of internal configuration parameters of `epg-gpg-program'."
+(defun epg-find-configuration (protocol &optional no-cache program-alist)
+  "Find or create a usable configuration to handle PROTOCOL.
+This function first looks at the existing configuration found by
+the previous invocation of this function, unless NO-CACHE is non-nil.
+
+Then it walks through PROGRAM-ALIST or
+`epg-config--program-alist'.  If `epg-gpg-program' or
+`epg-gpgsm-program' is already set with custom, use it.
+Otherwise, it tries the programs listed in the entry until the
+version requirement is met."
+  (unless program-alist
+    (setq program-alist epg-config--program-alist))
+  (let ((entry (assq protocol program-alist)))
+    (unless entry
+      (error "Unknown protocol %S" protocol))
+    (cl-destructuring-bind (symbol . alist)
+        (cdr entry)
+      (let ((constructor
+             (alist-get protocol epg-config--configuration-constructor-alist)))
+        (or (and (not no-cache) (alist-get protocol epg--configurations))
+            ;; If the executable value is already set with M-x
+            ;; customize, use it without checking.
+            (if (and symbol (get symbol 'saved-value))
+                (let ((configuration
+                       (funcall constructor (symbol-value symbol))))
+                  (push (cons protocol configuration) epg--configurations)
+                  configuration)
+              (catch 'found
+                (dolist (program-version alist)
+                  (let ((executable (executable-find (car program-version))))
+                    (when executable
+                      (let ((configuration
+                             (funcall constructor executable)))
+                        (when (ignore-errors
+                                (epg-check-configuration configuration
+                                                         (cdr program-version))
+                                t)
+                          (unless no-cache
+                            (push (cons protocol configuration)
+                                  epg--configurations))
+                          (throw 'found configuration)))))))))))))
+
+;; Create an `epg-configuration' object for `gpg', using PROGRAM.
+(defun epg-config--make-gpg-configuration (program)
   (let (config groups type args)
     (with-temp-buffer
-      (apply #'call-process epg-gpg-program nil (list t nil) nil
+      (apply #'call-process program nil (list t nil) nil
             (append (if epg-gpg-home-directory
                         (list "--homedir" epg-gpg-home-directory))
                     '("--with-colons" "--list-config")))
@@ -106,10 +181,30 @@ Note that the buffer name starts with a space."
                         type args))))
         (t
          (setq config (cons (cons type args) config))))))
+    (push (cons 'program program) config)
     (if groups
        (cons (cons 'groups groups) config)
       config)))
 
+;; Create an `epg-configuration' object for `gpgsm', using PROGRAM.
+(defun epg-config--make-gpgsm-configuration (program)
+  (with-temp-buffer
+    (call-process program nil (list t nil) nil "--version")
+    (goto-char (point-min))
+    (when (looking-at "\\S-+ (")
+      (goto-char (match-end 0))
+      (backward-char)
+      (forward-sexp)
+      (skip-syntax-forward "-" (point-at-eol))
+      (list (cons 'program program)
+            (cons 'version (buffer-substring (point) (point-at-eol)))))))
+
+;;;###autoload
+(defun epg-configuration ()
+  "Return a list of internal configuration parameters of `epg-gpg-program'."
+  (declare (obsolete epg-find-configuration "25.1"))
+  (epg-config--make-gpg-configuration epg-gpg-program))
+
 (defun epg-config--parse-version (string)
   (let ((index 0)
        version)