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?