How to get avatars of users in Jabber using libstrophe

958 Views Asked by At

How can I fetch the avatars of all the contacts in a user's XMPP/Jabber roster?

I have previously asked this question, and while implementing the <presence> handler, I noticed that the presence items my app receives are of the form:

<presence to="me" from="contact">
...some other stuff here...
<x xmlns="vcard-temp:x:update"><photo>3FB991AA97D7701C21EAFE65FB866E4BFF1B927C</photo></x>
</presence>

The 3FB991AA97D7701C21EAFE65FB866E4BFF1B927C part looks like a SHA hash to me, but how can I get the actual avatar of the user in question?

1

There are 1 best solutions below

2
On

vCard-based Avatars are specified in XEP-0153. You are correct that the photo element contains a SHA1 hash. Request the vCard of the person that sent you the hash:

<iq to='[email protected]'
    type='get' 
    id='vc2'>
  <vCard xmlns='vcard-temp'/>
</iq>

And fish the photo out of the response:

<iq to='[email protected]/orchard' 
    type='result'
    id='vc2'>
  <vCard xmlns='vcard-temp'>
    <PHOTO>
      <TYPE>image/jpeg</TYPE>
      <BINVAL>
        Base64-encoded-avatar-file-here!
      </BINVAL>
    </PHOTO>
  </vCard>
</iq>

You MUST cache based on that if you're going to use this protocol, and you'll really want to throttle how often you ask for avatars when you start up (particularly the first time a user logs in). Grabbing bajillions of avatars in a short amount of time will likely get you rate-limited by your server otherwise.

Also, be very careful about calculating your SHA1 hash. I've seen several clients that aren't terribly careful, who end up in an endless loop re-requesting the same avatar over and over.

I suggest negative-caching if you request an avatar and it doesn't match the hash you expect; cache the fact that you aren't going to get an answer for that hash, and don't ask for it again next time. The sender's SHA1 logic is likely wrong in some interesting way, and it's not going to get better the next time you ask.

Finally, some clients are written to try asking the sender's server for vCard data using XEP-0054 first as XEP-0153 says, then fall back on asking the sender's client directly by sending an IQ get for the vCard to the sender's full JID (user@domain/resource). Be prepared to deal with those requests on the sender's side.