X-Git-Url: https://cgit.sxemacs.org/?p=gnus;a=blobdiff_plain;f=lisp%2Fauth-source.el;h=eede3533510eb214a044a556fbc2d400c20931cf;hp=a5be12999283e37a2c72616672ff6294ac78326d;hb=82f3e557de7ffb57fce527be64009239d084db77;hpb=0fc67199d3aa4635aaa5fd230f9b14f2385a0559 diff --git a/lisp/auth-source.el b/lisp/auth-source.el index a5be12999..eede35335 100644 --- a/lisp/auth-source.el +++ b/lisp/auth-source.el @@ -463,8 +463,8 @@ which says: search to find only entries that have P set to 'pppp'.\" When multiple values are specified in the search parameter, the -first one is used for creation. So :host (X Y Z) would create a -token for host X, for instance. +user is prompted for which one. So :host (X Y Z) would ask the +user to choose between X, Y, and Z. This creation can fail if the search was not specific enough to create a new token (it's up to the backend to decide that). You @@ -510,7 +510,7 @@ must call it to obtain the actual value." unless (memq (nth i spec) ignored-keys) collect (nth i spec))) (found (auth-source-recall spec)) - filtered-backends accessor-key found-here goal) + filtered-backends accessor-key found-here goal matches) (if (and found auth-source-do-cache) (auth-source-do-debug @@ -539,38 +539,60 @@ must call it to obtain the actual value." ;; (debug spec "filtered" filtered-backends) (setq goal max) - (dolist (backend filtered-backends) - (setq found-here (apply - (slot-value backend 'search-function) - :backend backend - :create create - :delete delete - spec)) - - ;; if max is 0, as soon as we find something, return it - (when (and (zerop max) (> 0 (length found-here))) - (return t)) - - ;; decrement the goal by the number of new results - (decf goal (length found-here)) - ;; and append the new results to the full list - (setq found (append found found-here)) - - (auth-source-do-debug - "auth-source-search: found %d results (max %d/%d) in %S matching %S" - (length found-here) max goal backend spec) - - ;; return full list if the goal is 0 or negative - (when (zerop (max 0 goal)) - (return found)) - - ;; change the :max parameter in the spec to the goal - (setq spec (plist-put spec :max goal))) - - (when (and found auth-source-do-cache) - (auth-source-remember spec found))) - - found)) + ;; First go through all the backends without :create, so we can + ;; query them all. + (let ((uspec (copy-sequence spec))) + (plist-put uspec :create nil) + (dolist (backend filtered-backends) + (let ((match (apply + (slot-value backend 'search-function) + :backend backend + uspec))) + (when match + (push (list backend match) matches))))) + ;; If we didn't find anything, then we allow the backend(s) to + ;; create the entries. + (when (and create + (not matches)) + (dolist (backend filtered-backends) + (unless matches + (let ((match (apply + (slot-value backend 'search-function) + :backend backend + :create create + :delete delete + spec))) + (when match + (push (list backend match) matches)))))) + + (setq backend (caar matches) + found-here (cadar matches)) + + (block nil + ;; if max is 0, as soon as we find something, return it + (when (and (zerop max) (> 0 (length found-here))) + (return t)) + + ;; decrement the goal by the number of new results + (decf goal (length found-here)) + ;; and append the new results to the full list + (setq found (append found found-here)) + + (auth-source-do-debug + "auth-source-search: found %d results (max %d/%d) in %S matching %S" + (length found-here) max goal backend spec) + + ;; return full list if the goal is 0 or negative + (when (zerop (max 0 goal)) + (return found)) + + ;; change the :max parameter in the spec to the goal + (setq spec (plist-put spec :max goal)) + + (when (and found auth-source-do-cache) + (auth-source-remember spec found)))) + + found)) ;;; (auth-source-search :max 1) ;;; (funcall (plist-get (nth 0 (auth-source-search :max 1)) :secret)) @@ -861,6 +883,7 @@ See `auth-source-search' for details on SPEC." (required (append base-required create-extra)) (file (oref backend source)) (add "") + (show "") ;; `valist' is an alist valist ;; `artificial' will be returned if no creation is needed @@ -868,12 +891,16 @@ See `auth-source-search' for details on SPEC." ;; only for base required elements (defined as function parameters): ;; fill in the valist with whatever data we may have from the search - ;; we take the first value if it's a list, the whole value otherwise + ;; we complete the first value if it's a list and use the value otherwise (dolist (br base-required) (when (symbol-value br) - (aput 'valist br (if (listp (symbol-value br)) - (nth 0 (symbol-value br)) - (symbol-value br))))) + (let ((br-choice (cond + ;; all-accepting choice (predicate is t) + ((eq t (symbol-value br)) nil) + ;; just the value otherwise + (t (symbol-value br))))) + (when br-choice + (aput 'valist br br-choice))))) ;; for extra required elements, see if the spec includes a value for them (dolist (er create-extra) @@ -904,6 +931,8 @@ See `auth-source-search' for details on SPEC." (user-value (aget valist 'user)) (host-value (aget valist 'host)) (port-value (aget valist 'port)) + ;; note this handles lists by just printing them + ;; later we allow the user to use completing-read to pick (info-so-far (concat (if user-value (format "%s@" user-value) "[USER?]") @@ -931,6 +960,16 @@ See `auth-source-search' for details on SPEC." (format "Enter %s for %s%s: " r info-so-far default-string) nil nil default)) + ((listp data) + (completing-read + (format "Enter %s for %s (TAB to see the choices): " + r info-so-far) + data + nil ; no predicate + t ; require a match + ;; note the default is nil, but if the user + ;; hits RET we'll get "", which is handled OK later + nil)) (t data)))) (when data @@ -944,20 +983,25 @@ See `auth-source-search' for details on SPEC." ;; when r is not an empty string... (when (and (stringp data) (< 0 (length data))) - ;; append the key (the symbol name of r) and the value in r - (setq add (concat add - (format "%s%s %S" - ;; prepend a space - (if (zerop (length add)) "" " ") - ;; remap auth-source tokens to netrc - (case r + (let ((printer (lambda (hide) + ;; append the key (the symbol name of r) + ;; and the value in r + (format "%s%s %S" + ;; prepend a space + (if (zerop (length add)) "" " ") + ;; remap auth-source tokens to netrc + (case r ('user "login") ('host "machine") ('secret "password") ('port "port") ; redundant but clearer (t (symbol-name r))) - ;; the value will be printed in %S format - data)))))) + ;; the value will be printed in %S format + (if (and hide (eq r 'secret)) + "HIDDEN_SECRET" + data))))) + (setq add (concat add (funcall printer nil))) + (setq show (concat show (funcall printer t))))))) (with-temp-buffer (when (file-exists-p file) @@ -974,7 +1018,7 @@ See `auth-source-search' for details on SPEC." (goto-char (point-max)) ;; ask AFTER we've successfully opened the file - (if (y-or-n-p (format "Add to file %s: line [%s]" file add)) + (if (y-or-n-p (format "Add to file %s: line [%s]" file show)) (progn (unless (bolp) (insert "\n"))