Support avatar images for contacts.

This commit is contained in:
plfiorini 2010-05-30 04:26:36 +00:00
parent 1644625480
commit 225957b2f6
3 changed files with 175 additions and 11 deletions

View File

@ -6,10 +6,16 @@
* Pier Luigi Fiorini, pierluigi.fiorini@gmail.com * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
*/ */
//#include <libsupport/Base64.h> #include <Directory.h>
#include <Entry.h>
#include <File.h>
#include <FindDirectory.h>
#include <List.h>
#include <CayaProtocolMessages.h> #include <CayaProtocolMessages.h>
#include <libsupport/SHA1.h>
#include "JabberHandler.h" #include "JabberHandler.h"
@ -31,6 +37,7 @@ JabberHandler::JabberHandler()
fClient(NULL), fClient(NULL),
fVCardManager(NULL) fVCardManager(NULL)
{ {
fAvatars = new BList();
} }
@ -38,6 +45,11 @@ JabberHandler::~JabberHandler()
{ {
fVCardManager->cancelVCardOperations(this); fVCardManager->cancelVCardOperations(this);
Shutdown(); Shutdown();
BString* item = NULL;
for (int32 i = 0; (item = (BString*)fAvatars->ItemAt(i)); i++)
delete item;
delete fAvatars;
} }
@ -204,6 +216,138 @@ JabberHandler::_MessageSent(const char* id, const char* subject,
} }
status_t
JabberHandler::_SetupAvatarCache()
{
if (fAvatarCachePath.InitCheck() == B_OK)
return B_OK;
BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
return B_ERROR;
path.Append("Caya");
path.Append("Cache");
path.Append(kProtocolSignature);
if (create_directory(path.Path(), 0755) != B_OK)
return B_ERROR;
fCachePath = path;
path.Append("avatar-cache");
BFile file(path.Path(), B_READ_ONLY);
fAvatarCache.Unflatten(&file);
fAvatarCachePath = path;
return B_OK;
}
status_t
JabberHandler::_SaveAvatarCache()
{
if (fAvatarCachePath.InitCheck() != B_OK)
return B_ERROR;
BFile file(fAvatarCachePath.Path(), B_CREATE_FILE | B_WRITE_ONLY | B_ERASE_FILE);
return fAvatarCache.Flatten(&file);
}
void
JabberHandler::_CacheAvatar(const char* id, const char* binimage, size_t length)
{
if (!id || !binimage || length <= 0)
return;
// Calculate avatar hash
CSHA1 s1;
char hash[256];
s1.Reset();
s1.Update((uchar*)binimage, length);
s1.Final();
s1.ReportHash(hash, CSHA1::REPORT_HEX);
BString sha1;
sha1.SetTo(hash, 256);
BString oldSha1;
if (fAvatarCache.FindString("id", &oldSha1) != B_OK || oldSha1 == "" || sha1 != oldSha1) {
// Replace old hash and save cache
fAvatarCache.RemoveName(id);
fAvatarCache.AddString(id, sha1);
_SaveAvatarCache();
if (oldSha1 != "") {
BPath path(fCachePath);
path.Append(oldSha1);
// Remove old image file
BEntry entry(path.Path());
entry.Remove();
// Remove old hash from the list
BString* item = NULL;
for (int32 i = 0; (item = (BString*)fAvatars->ItemAt(i)); i++) {
if (item->Compare(oldSha1) == 0) {
fAvatars->RemoveItem(item);
break;
}
}
}
}
// Determine file path
BPath path(fCachePath);
path.Append(sha1);
BEntry entry(path.Path());
if (!entry.Exists()) {
// Save to file
BFile file(path.Path(), B_CREATE_FILE | B_WRITE_ONLY | B_ERASE_FILE);
file.Write(binimage, length);
}
// Do we need to notify Caya?
bool found = false;
BString* item = NULL;
for (int32 i = 0; (item = (BString*)fAvatars->ItemAt(i)); i++) {
if (item->Compare(sha1) == 0) {
found = true;
break;
}
}
if (!found) {
// Add new hash to the list if needed
fAvatars->AddItem(new BString(sha1));
// Notify Caya that the avatar has changed
_AvatarChanged(id, path.Path());
}
}
void
JabberHandler::_AvatarChanged(const char* id, const char* filename)
{
entry_ref ref;
if (get_ref_for_path(filename, &ref) != B_OK)
return;
BMessage msg(IM_MESSAGE);
msg.AddInt32("im_what", IM_AVATAR_SET);
msg.AddString("protocol", kProtocolSignature);
msg.AddString("id", id);
msg.AddRef("ref", &ref);
fServerMessenger->SendMessage(&msg);
}
CayaStatus CayaStatus
JabberHandler::_GlooxStatusToCaya(gloox::Presence::PresenceType type) JabberHandler::_GlooxStatusToCaya(gloox::Presence::PresenceType type)
{ {
@ -456,11 +600,6 @@ JabberHandler::handleVCard(const gloox::JID& jid, const gloox::VCard* card)
std::string fullName = name.family + " " + name.given; std::string fullName = name.family + " " + name.given;
#if 0
BString decoded
= Base64::Decode(BString(photo.binval.c_str()));
#endif
BMessage msg(IM_MESSAGE); BMessage msg(IM_MESSAGE);
msg.AddInt32("im_what", IM_EXTENDED_CONTACT_INFO); msg.AddInt32("im_what", IM_EXTENDED_CONTACT_INFO);
msg.AddString("protocol", kProtocolSignature); msg.AddString("protocol", kProtocolSignature);
@ -473,6 +612,15 @@ JabberHandler::handleVCard(const gloox::JID& jid, const gloox::VCard* card)
msg.AddString("suffix", name.suffix.c_str()); msg.AddString("suffix", name.suffix.c_str());
msg.AddString("full name", fullName.c_str()); msg.AddString("full name", fullName.c_str());
fServerMessenger->SendMessage(&msg); fServerMessenger->SendMessage(&msg);
// Return if there's no avatar icon
if (!photo.binval.c_str())
return;
if (_SetupAvatarCache() == B_OK)
// Cache avatar icon
_CacheAvatar(jid.bare().c_str(), photo.binval.c_str(),
photo.binval.length());
} }

View File

@ -5,6 +5,7 @@
#ifndef _JABBER_HANDLER_H #ifndef _JABBER_HANDLER_H
#define _JABBER_HANDLER_H #define _JABBER_HANDLER_H
#include <Path.h>
#include <String.h> #include <String.h>
#include <libgloox/client.h> #include <libgloox/client.h>
@ -21,8 +22,10 @@
#include <libgloox/vcardhandler.h> #include <libgloox/vcardhandler.h>
#include <libgloox/vcardmanager.h> #include <libgloox/vcardmanager.h>
#include "CayaProtocol.h" #include <CayaProtocol.h>
#include "CayaConstants.h" #include <CayaConstants.h>
class BList;
class JabberHandler : public CayaProtocol, gloox::RosterListener, gloox::ConnectionListener, class JabberHandler : public CayaProtocol, gloox::RosterListener, gloox::ConnectionListener,
gloox::LogHandler, gloox::MessageHandler, gloox::VCardHandler { gloox::LogHandler, gloox::MessageHandler, gloox::VCardHandler {
@ -66,10 +69,20 @@ private:
thread_id fRecvThread; thread_id fRecvThread;
BPath fCachePath;
BPath fAvatarCachePath;
BMessage fAvatarCache;
BList* fAvatars;
void _MessageSent(const char* id, const char* subject, void _MessageSent(const char* id, const char* subject,
const char* body); const char* body);
CayaStatus _GlooxStatusToCaya(gloox::Presence::PresenceType type); CayaStatus _GlooxStatusToCaya(gloox::Presence::PresenceType type);
status_t _SetupAvatarCache();
status_t _SaveAvatarCache();
void _CacheAvatar(const char* id, const char* binval, size_t length);
void _AvatarChanged(const char*id, const char* filename);
virtual void onConnect(); virtual void onConnect();
virtual void onDisconnect(gloox::ConnectionError); virtual void onDisconnect(gloox::ConnectionError);
virtual bool onTLSConnect(const gloox::CertInfo&); virtual bool onTLSConnect(const gloox::CertInfo&);

View File

@ -9,7 +9,7 @@ AddOn jabber :
JabberMain.cpp JabberMain.cpp
JabberProtocol.cpp JabberProtocol.cpp
JabberHandler.cpp JabberHandler.cpp
: be libgloox.a network ssl crypto z $(TARGET_LIBSTDC++) : be libsupport.a libgloox.a network ssl crypto z $(TARGET_LIBSTDC++)
: jabber.rdef jabber_settings.rdef : jabber.rdef jabber_settings.rdef
; ;
@ -17,7 +17,7 @@ AddOn gtalk :
GoogleTalkMain.cpp GoogleTalkMain.cpp
GoogleTalkProtocol.cpp GoogleTalkProtocol.cpp
JabberHandler.cpp JabberHandler.cpp
: be libgloox.a network ssl crypto z $(TARGET_LIBSTDC++) : be libsupport.a libgloox.a network ssl crypto z $(TARGET_LIBSTDC++)
: gtalk.rdef gtalk_settings.rdef : gtalk.rdef gtalk_settings.rdef
; ;
@ -25,12 +25,15 @@ AddOn facebook :
FacebookMain.cpp FacebookMain.cpp
FacebookProtocol.cpp FacebookProtocol.cpp
JabberHandler.cpp JabberHandler.cpp
: be libgloox.a network ssl crypto z $(TARGET_LIBSTDC++) : be libsupport.a libgloox.a network ssl crypto z $(TARGET_LIBSTDC++)
: facebook.rdef facebook_settings.rdef : facebook.rdef facebook_settings.rdef
; ;
Depends jabber : libsupport.a ;
Depends jabber : libgloox.a ; Depends jabber : libgloox.a ;
Depends gtalk : libsupport.a ;
Depends gtalk : libgloox.a ; Depends gtalk : libgloox.a ;
Depends facebook : libsupport.a ;
Depends facebook : libgloox.a ; Depends facebook : libgloox.a ;
LINKFLAGS on jabber += -L$(OPENSSL_LIBRARY_DIR) ; LINKFLAGS on jabber += -L$(OPENSSL_LIBRARY_DIR) ;