;;;; XEP-0115: Entity Capabilities (in-package :whatsxmpp) (defun format-disco-identity (name type category &optional (lang "")) "Formats a disco#info identity into a verification string part." (format nil "~A/~A/~A/~A" category type lang name)) (defun generate-entity-caps (disco-info-list) "Using DISCO-INFO-LIST, a quoted list of calls to DISCO-IDENTITY and DISCO-FEATURE, generate and return an XEP-0115 verification string. WARNING: You must pre-sort DISCO-INFO-LIST according to the rules in XEP-0115 ยง 5.1." (let (identities features) (loop for call in disco-info-list do (ecase (car call) (disco-identity (push (cdr call) identities)) (disco-feature (push (cdr call) features)))) (qbase64:encode-bytes (ironclad:digest-sequence :sha1 (babel:string-to-octets (format nil "~{~A<~}~{~A<~}" (mapcar (lambda (call) ;; Because DISCO-IDENTITY and FORMAT-DISCO-IDENTITY ;; intentionally take the same lambda lists, ;; we can just do this. (apply #'format-disco-identity call)) ;; NREVERSE because pushing things does it the wrong ;; way round (FIXME, inefficient) (nreverse identities)) ;; DISCO-FEATURE takes one argument (the feature name) (mapcar #'car (nreverse features))))))))