branch: elpa/jabber
commit 4e96ed6f0c2068062be528defbe0dac9e01ea05d
Author: Thanos Apollo <[email protected]>
Commit: Thanos Apollo <[email protected]>
pep: Implement XEP-0163 Personal Eventing Protocol
Advertise +notify disco features for OMEMO device list and OpenPGP
public keys so the server auto-delivers PEP events mid-session.
Add jabber-openpgp--handle-keys-event to fetch updated keys when a
contact publishes new OpenPGP key metadata via PEP.
Validate that PEP events come from bare JIDs per XEP-0163 s4.3 in
jabber-pubsub--process-event, rejecting full JIDs as malformed.
---
doap.xml | 8 ++++++++
lisp/jabber-omemo.el | 1 +
lisp/jabber-openpgp.el | 40 +++++++++++++++++++++++++++++++++++++++-
lisp/jabber-pubsub.el | 28 +++++++++++++++-------------
4 files changed, 63 insertions(+), 14 deletions(-)
diff --git a/doap.xml b/doap.xml
index 7580175340..58a4b4cbbb 100644
--- a/doap.xml
+++ b/doap.xml
@@ -326,6 +326,14 @@
<xmpp:note>The pixel size limits on avatars are not
enforced.</xmpp:note>
</xmpp:SupportedXep>
</implements>
+ <implements>
+ <xmpp:SupportedXep>
+ <xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0163.html"/>
+ <xmpp:status>complete</xmpp:status>
+ <xmpp:version>1.2.2</xmpp:version>
+ <xmpp:since>0.10.1-alpha</xmpp:since>
+ </xmpp:SupportedXep>
+ </implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0184.html"/>
diff --git a/lisp/jabber-omemo.el b/lisp/jabber-omemo.el
index eb13769988..424e83742d 100644
--- a/lisp/jabber-omemo.el
+++ b/lisp/jabber-omemo.el
@@ -1310,6 +1310,7 @@ Returns non-nil if handled, nil to fall through to
plaintext."
;;; Disco and PubSub registration
(jabber-disco-advertise-feature jabber-omemo-xmlns)
+(jabber-disco-advertise-feature (concat jabber-omemo-devicelist-node
"+notify"))
(with-eval-after-load "jabber-pubsub"
(push (cons jabber-omemo-devicelist-node
diff --git a/lisp/jabber-openpgp.el b/lisp/jabber-openpgp.el
index 8840361e8c..3740107664 100644
--- a/lisp/jabber-openpgp.el
+++ b/lisp/jabber-openpgp.el
@@ -443,9 +443,47 @@ OPENPGP-EL is the <openpgp> child element."
(jabber-chat--set-body xml-data
(or body-text "[OpenPGP: empty payload]"))))
-;;; Disco and hooks
+;;; Disco, PubSub registration, and hooks
(jabber-disco-advertise-feature jabber-openpgp-xmlns)
+(jabber-disco-advertise-feature (concat jabber-openpgp-pubkeys-node "+notify"))
+
+(defun jabber-openpgp--handle-keys-event (jc from _node items)
+ "Handle PubSub event for OpenPGP public key updates.
+JC is the connection, FROM is the sender JID, ITEMS is the list
+of child elements from the event. Fetches updated key into the
+local GPG keyring."
+ (let* ((item-el (car items))
+ (keys-list (and (listp item-el)
+ (car (jabber-xml-get-children
+ item-el 'public-keys-list))))
+ (meta (and keys-list
+ (car (jabber-xml-get-children
+ keys-list 'pubkey-metadata))))
+ (fingerprint (and meta
+ (jabber-xml-get-attribute meta 'v4-fingerprint)))
+ (jid (jabber-jid-user from)))
+ (if (null fingerprint)
+ (message "OpenPGP: key update from %s but no fingerprint in metadata"
jid)
+ (message "OpenPGP: %s updated key %s, fetching..." jid fingerprint)
+ (let ((node (concat jabber-openpgp-pubkeys-node ":" fingerprint)))
+ (jabber-pubsub-request
+ jc jid node
+ (lambda (_jc xml-data _closure)
+ (jabber-openpgp--handle-key-response
+ xml-data fingerprint
+ (lambda (key)
+ (if key
+ (message "OpenPGP: imported updated key for %s" jid)
+ (message "OpenPGP: failed to import key for %s" jid)))))
+ (lambda (_jc _xml-data _closure)
+ (message "OpenPGP: failed to fetch key %s for %s"
+ fingerprint jid)))))))
+
+(with-eval-after-load "jabber-pubsub"
+ (push (cons jabber-openpgp-pubkeys-node
+ #'jabber-openpgp--handle-keys-event)
+ jabber-pubsub-node-handlers))
(jabber-chat-register-decrypt-handler
'openpgp
diff --git a/lisp/jabber-pubsub.el b/lisp/jabber-pubsub.el
index 5ffd6a2cfd..9d019e0e4d 100644
--- a/lisp/jabber-pubsub.el
+++ b/lisp/jabber-pubsub.el
@@ -138,19 +138,21 @@ where ITEMS is the list of child elements (item or
retract).")
(defun jabber-pubsub--process-event (jc xml-data)
"Process incoming PubSub event notifications.
-JC is the Jabber connection. XML-DATA is the message stanza."
- (let ((event (jabber-xml-child-with-xmlns xml-data
jabber-pubsub-event-xmlns)))
- (when event
- (let* ((items-or-purge (or (car (jabber-xml-get-children event 'items))
- (car (jabber-xml-get-children event 'purge))))
- (node (and items-or-purge
- (jabber-xml-get-attribute items-or-purge 'node)))
- (handler (and node (cdr (assoc node
jabber-pubsub-node-handlers)))))
- (when handler
- (funcall handler jc
- (jabber-xml-get-attribute xml-data 'from)
- node
- (jabber-xml-node-children items-or-purge)))))))
+JC is the Jabber connection. XML-DATA is the message stanza.
+Per XEP-0163 s4.3, PEP events MUST come from bare JIDs."
+ (let* ((event (jabber-xml-child-with-xmlns xml-data
jabber-pubsub-event-xmlns))
+ (from (and event (jabber-xml-get-attribute xml-data 'from))))
+ (when (and event from)
+ (if (jabber-jid-resource from)
+ (message "PubSub: ignoring event from full JID %s" from)
+ (let* ((items-or-purge (or (car (jabber-xml-get-children event 'items))
+ (car (jabber-xml-get-children event
'purge))))
+ (node (and items-or-purge
+ (jabber-xml-get-attribute items-or-purge 'node)))
+ (handler (and node (cdr (assoc node
jabber-pubsub-node-handlers)))))
+ (when handler
+ (funcall handler jc from node
+ (jabber-xml-node-children items-or-purge))))))))
(with-eval-after-load "jabber-core"
(jabber-chain-add 'jabber-message-chain #'jabber-pubsub--process-event))