Emacs 26.1: secret-search-items bug: dbus-call-method: (wrong-type-argument consp "host") [workaround]
Bug has been reported and fixed.
My emacs version:
GNU Emacs 26.1
My smtpmail
is configured to use secrets, resulting in the following call:
(secrets-search-items "Default" :host "myhost" :port "587" :user "myuser")
Since the 26.1 upgrade this resulted in:
Debugger entered--Lisp error: (wrong-type-argument consp "host") dbus-message-internal(1 :session "org.freedesktop.secrets" "/org/freedesktop/secrets/collection/Default" "org.freedesktop.Secret.Collection" "SearchItems" dbus-call-method-handler (:array :dict-entry "host" "myhost" :dict-entry "port" "587" :dict-entry "user" "myuser")) apply(dbus-message-internal 1 :session "org.freedesktop.secrets" "/org/freedesktop/secrets/collection/Default" "org.freedesktop.Secret.Collection" "SearchItems" dbus-call-method-handler (:array :dict-entry "host" "myhost" :dict-entry "port" "587" :dict-entry "user" "myuser")) dbus-call-method(:session "org.freedesktop.secrets" "/org/freedesktop/secrets/collection/Default" "org.freedesktop.Secret.Collection" "SearchItems" (:array :dict-entry "host" "myhost" :dict-entry "port" "587" :dict-entry "user" "myuser")) secrets-search-items("Default" :host "myhost" :port "587" :user "myuser")
dbus-call-method
expects arrays with dict-entries to provide a cons:
A dictionary entry must be element of an array, and it must contain only a key-value pair of two elements, with a basic D-Bus type key.
So in this example, dbus-call-method
expects
'(:array :dict-entry ("host" "myhost"))
rather than
'(:array :dict-entry "host" "myhost")
secret-search-items
builds this list incorrectly:
(defun secrets-search-items (collection &rest attributes) "Search items in COLLECTION with ATTRIBUTES. ATTRIBUTES are key-value pairs. The keys are keyword symbols, starting with a colon. Example: (secrets-search-items \"Tramp collection\" :user \"joe\") The object labels of the found items are returned as list." (let ((collection-path (secrets-unlock-collection collection)) result props) (unless (secrets-empty-path collection-path) ;; Create attributes list. (while (consp (cdr attributes)) (unless (keywordp (car attributes)) (error 'wrong-type-argument (car attributes))) (unless (stringp (cadr attributes)) (error 'wrong-type-argument (cadr attributes))) (setq props (append props (list :dict-entry ;; FIXME ------------------ (substring (symbol-name (car attributes)) 1) (cadr attributes))) attributes (cddr attributes))) ;; Search. The result is a list of object paths. (setq result (dbus-call-method :session secrets-service collection-path secrets-interface-collection "SearchItems" (if props (cons :array props) '(:array :signature "{ss}")))) ;; Return the found items. (mapcar (lambda (item-path) (secrets-get-item-property item-path "Label")) result))))
Let's fix this function so that it constructs arguments using list
:
(defun secrets-search-items (collection &rest attributes) "Search items in COLLECTION with ATTRIBUTES. ATTRIBUTES are key-value pairs. The keys are keyword symbols, starting with a colon. Example: (secrets-search-items \"Tramp collection\" :user \"joe\") The object labels of the found items are returned as list." (let ((collection-path (secrets-unlock-collection collection)) result props) (unless (secrets-empty-path collection-path) ;; Create attributes list. (while (consp (cdr attributes)) (unless (keywordp (car attributes)) (error 'wrong-type-argument (car attributes))) (unless (stringp (cadr attributes)) (error 'wrong-type-argument (cadr attributes))) (setq props (append props (list :dict-entry ;; HACK fixed so that dict entries are conses (list (substring (symbol-name (car attributes)) 1) (cadr attributes)))) attributes (cddr attributes))) (prin1 props) ;; Search. The result is a list of object paths. (setq result (dbus-call-method :session secrets-service collection-path secrets-interface-collection "SearchItems" (if props (cons :array props) '(:array :signature "{ss}")))) ;; Return the found items. (mapcar (lambda (item-path) (secrets-get-item-property item-path "Label")) result))))
Or as define-advice so that we can easily hotfix:
(define-advice secrets-search-items (:override (collection &rest attributes) my-secrets-search-fixed) "Fix cons building in dbus-call-method call" (let ((collection-path (secrets-unlock-collection collection)) result props) (unless (secrets-empty-path collection-path) ;; Create attributes list. (while (consp (cdr attributes)) (unless (keywordp (car attributes)) (error 'wrong-type-argument (car attributes))) (unless (stringp (cadr attributes)) (error 'wrong-type-argument (cadr attributes))) (setq props (append props (list :dict-entry (substring (symbol-name (car attributes)) 1) (cadr attributes))) attributes (cddr attributes))) ;; Search. The result is a list of object paths. (setq result (dbus-call-method :session secrets-service collection-path secrets-interface-collection "SearchItems" (if props (cons :array props) '(:array :signature "{ss}")))) ;; Return the found items. (mapcar (lambda (item-path) (secrets-get-item-property item-path "Label")) result))))
Questions
- Did secrets change, or did dbus change?
- Is this bug reported already?