Changeset 6181

Show
Ignore:
Timestamp:
05/05/08 16:31:53 (5 months ago)
Author:
emostar
Message:

Add the patch by Sergey Kononenko (Message-ID: <20080122012616.48112055@…>)
Included the following additions:

  • Add support for AIM (not all users yet)
  • Fix a few memory leaks
  • Rename SSBI to BART
  • Add constants for BART Types
  • Add support to qt4-gui
  • Use boost in a few cases
Location:
trunk
Files:
2 added
24 modified

Legend:

Unmodified
Added
Removed
  • trunk/licq/include/licq_buffer.h

    r6168 r6181  
    127127   CBuffer& operator >> (unsigned long &in); 
    128128   char *UnpackRaw(char *, unsigned short); 
     129   char *UnpackBinBlock(char *, unsigned short); 
    129130   char *UnpackString(char *, unsigned short); 
    130131   char *UnpackString();                // Need to delete[] returned string 
  • trunk/licq/include/licq_events.h

    r6180 r6181  
    248248 
    249249  // Daemon only 
    250   unsigned short SubType() const { return m_nSubType; } 
    251   unsigned short ExtraInfo() const { return m_nExtraInfo; } 
     250  unsigned short SubType() const     { return m_nSubType; } 
     251  unsigned short ExtraInfo() const   { return m_nExtraInfo; } 
     252  void SetSubType(unsigned short nSubType) { m_nSubType = nSubType; } 
     253  bool NoAck() const           { return m_NoAck; } 
     254  void SetNoAck(bool NoAck)    { m_NoAck = NoAck; } 
     255  bool IsCancelled() const     { return m_bCancelled; } 
     256 
     257  void AttachPacket(CPacket *p); 
    252258 
    253259  // Compare this event to another one 
     
    291297 
    292298friend class CICQDaemon; 
     299friend class COscarService; 
    293300friend class CMSN; 
    294301friend void *ProcessRunningEvent_Client_tep(void *p); 
    295302friend void *ProcessRunningEvent_Server_tep(void *p); 
     303friend void *OscarServiceSendQueue_tep(void *p); 
    296304friend void *MonitorSockets_tep(void *p); 
    297305}; 
     
    477485  //! The user has requested to update the owner's profile/information. 
    478486  PROTOxUPDATExINFO, 
     487  //! The user has requested the user's picture/icon/avatar/etc.. 
     488  PROTOxREQUESTxPICTURE, 
    479489  //! The user has requested this user be added to the Invisible/Block list. 
    480490  PROTOxBLOCKxUSER, 
     
    685695}; 
    686696 
     697class CRequestPicture : public CSignal 
     698{ 
     699public: 
     700  CRequestPicture(const char *); 
     701  virtual ~CRequestPicture(); 
     702}; 
     703 
    687704class CBlockUserSignal : public CSignal 
    688705{ 
  • trunk/licq/include/licq_icq.h

    r5972 r6181  
    3535const unsigned short ICQ_SNACxFAM_MESSAGE          = 0x0004; 
    3636const unsigned short ICQ_SNACxFAM_BOS              = 0x0009; 
     37const unsigned short ICQ_SNACxFAM_BART             = 0x0010; 
    3738const unsigned short ICQ_SNACxFAM_LIST             = 0x0013; 
    3839const unsigned short ICQ_SNACxFAM_VARIOUS          = 0x0015; 
     
    104105const unsigned short ICQ_SNACxREQUEST_IMAGE        = 0x000C; // client 
    105106const unsigned short ICQ_SNACxSEND_IMAGE           = 0x000D; // server 
     107 
     108// Subtypes for BART family 
     109const unsigned short ICQ_SNACxBART_ERROR           = 0x0001; // server 
     110const unsigned short ICQ_SNACxBART_UPLOAD          = 0x0002; // client 
     111const unsigned short ICQ_SNACxBART_UPLOADxACK      = 0x0003; // server 
     112const unsigned short ICQ_SNACxBART_DOWNLOADxREQUEST= 0x0006; // client 
     113const unsigned short ICQ_SNACxBART_DOWNLOADxREPLY  = 0x0007; // server 
    106114 
    107115// Subtypes for list family 
     
    469477const unsigned short CHARSET_CUSTOM  = 0x0003; 
    470478 
     479// BART Types 
     480const unsigned short BART_TYPExBUDDY_ICON_SMALL = 0x0000; 
     481const unsigned short BART_TYPExBUDDY_ICON       = 0x0001; 
     482const unsigned short BART_TYPExSTATUS_STR       = 0x0002; 
     483 
    471484//actual plugins 
    472485const char PLUGIN_PHONExBOOK[]        = { 0x90, 0x7C, 0x21, 0x2C, 0x91, 0x4D, 
     
    544557                                          0x4E, 0xC5, 0x9D, 0x51, 0xA6, 0x47, 
    545558                                          0x4E, 0x34, 0xF5, 0xA0 }; 
     559 
     560const char ICQ_CAPABILITY_BART[]      = { 0x09, 0x46, 0x13, 0x46, 0x4C, 0x7F, 
     561                                          0x11, 0xD1, 0x82, 0x22, 0x44, 0x45, 
     562                                          0x53, 0x54, 0x00, 0x00 }; 
    546563 
    547564const char ICQ_CAPABILITY_LICQxVER[]  = { 'L',  'i',  'c',  'q',  ' ',  'c', 
  • trunk/licq/include/licq_icqd.h

    r6180 r6181  
    4343class INetSocket; 
    4444class ProxyServer; 
     45class COscarService; 
    4546class CReverseConnectToUserData; 
    4647class CMSN; 
     
    300301    const char *szFaxNumber, const char *szAddress, const char *szCellularNumber, 
    301302    const char *szZipCode, unsigned short nCountryCode, bool bHideEmail); 
     303 
     304  unsigned long ProtoRequestPicture(const char *szId, unsigned long nPPID); 
    302305 
    303306  unsigned long ProtoOpenSecureChannel(const char *szId, unsigned long nPPID); 
     
    476479  void icqTypingNotification(const char *_szId, bool _bActive); 
    477480  void icqCheckInvisible(const char *_szId); 
     481  void icqRequestService(unsigned short nFam); 
    478482 
    479483  // Visible/Invisible/Ignore list functions 
     
    516520  char *ProtoPluginName(unsigned long); 
    517521 
     522  EDaemonStatus Status() { return m_eStatus; } 
     523 
    518524  void PluginUIViewEvent(const char *szId, unsigned long nPPID ) { 
    519525    PushPluginSignal(new CICQSignal(SIGNAL_UI_VIEWEVENT, 0, szId, nPPID, 0)); 
     
    569575  // Proxy options 
    570576  void InitProxy(); 
     577  ProxyServer *CreateProxy(); 
    571578  bool ProxyEnabled() {  return m_bProxyEnabled;  } 
     579  ProxyServer *GetProxy() {  return m_xProxy;  } 
    572580  void SetProxyEnabled(bool b) {  m_bProxyEnabled = b;  } 
    573581  unsigned short ProxyType() {  return m_nProxyType;  } 
     
    611619  // ICQ options 
    612620  bool UseServerContactList()         { return m_bUseSS; } 
     621  bool UseServerSideBuddyIcons()      { return m_bUseBART; } 
    613622  bool SendTypingNotification()       { return m_bSendTN; } 
    614623 
    615   void SetUseServerContactList(bool b)   { m_bUseSS = b; } 
    616   void SetSendTypingNotification(bool b) { m_bSendTN = b; } 
     624  void SetUseServerContactList(bool b)    { m_bUseSS = b; } 
     625  void SetUseServerSideBuddyIcons(bool b); 
     626  void SetSendTypingNotification(bool b)  { m_bSendTN = b; } 
    617627 
    618628  // Misc functions 
     
    702712  ProxyServer *m_xProxy; 
    703713 
     714  // Services 
     715  COscarService *m_xBARTService; 
     716 
    704717  // Misc 
    705718  bool m_bUseSS; // server side list 
     719  bool m_bUseBART; // server side buddy icons 
    706720  bool m_bSendTN; // Send typing notifications 
    707721  bool m_bReconnectAfterUinClash; // reconnect after uin has been used from another location? 
     
    731745            thread_ping, 
    732746            thread_updateusers, 
     747            thread_ssbiservice, 
    733748            thread_shutdown; 
    734749 
     
    764779  bool hasServerEvent(unsigned long); 
    765780  void ProcessDoneEvent(ICQEvent *); 
     781  void PushEvent(ICQEvent *); 
    766782  void PushExtendedEvent(ICQEvent *); 
    767783  void PushPluginSignal(CICQSignal *); 
     
    832848  friend void *ProcessRunningEvent_Client_tep(void *p); 
    833849  friend void *ProcessRunningEvent_Server_tep(void *p); 
     850  friend void *OscarServiceSendQueue_tep(void *p); 
    834851  friend void *Shutdown_tep(void *p); 
    835852  friend void *ConnectToServer_tep(void *s); 
    836853  friend class ICQUser; 
    837854  friend class CSocketManager; 
     855  friend class COscarService; 
    838856  friend class CChatManager; 
    839857  friend class CFileTransferManager; 
  • trunk/licq/include/licq_packets.h

    r6180 r6181  
    135135 
    136136  static bool s_bRegistered; 
    137   static unsigned short s_nSequence; 
     137  static unsigned short s_nSequence[32]; 
    138138  static unsigned short s_nSubSequence; 
    139139  static pthread_mutex_t s_xMutex; 
     
    146146  unsigned short m_nSubCommand; 
    147147  unsigned short m_nExtraInfo; 
     148  unsigned short m_nService; 
    148149 
    149150  char *m_szSequenceOffset; 
     
    220221{ 
    221222public: 
    222   CPU_SendCookie(const char *, int len); 
     223  CPU_SendCookie(const char *, int len, unsigned short nService = 0); 
    223224  virtual ~CPU_SendCookie(); 
    224225}; 
     
    238239{ 
    239240public: 
    240   CPU_GenericFamily(unsigned short Family, unsigned short SubType); 
     241  CPU_GenericFamily(unsigned short Family, unsigned short SubType, 
     242                    unsigned short nService = 0); 
    241243  virtual ~CPU_GenericFamily(); 
    242244}; 
     
    320322{ 
    321323public: 
    322     CPU_ImICQ(); 
     324  CPU_ImICQ(); 
     325  CPU_ImICQ(unsigned short VerArray[][2], unsigned short NumVer, 
     326            unsigned short nService); 
    323327}; 
    324328 
     
    341345{ 
    342346public: 
    343   CPU_RateAck(); 
     347  CPU_RateAck(unsigned short nService = 0); 
    344348}; 
    345349 
     
    495499public: 
    496500   CPU_ClientReady(); 
     501   CPU_ClientReady(unsigned short VerArray[][4], unsigned short NumVer, 
     502                   unsigned short nService); 
    497503}; 
    498504 
     
    11341140}; 
    11351141 
     1142//-----RequestBuddyIcon------------------------------------------------------ 
     1143class CPU_RequestBuddyIcon : public CPU_CommonFamily 
     1144{ 
     1145public: 
     1146  CPU_RequestBuddyIcon(const char *szId, unsigned short _nBuddyIconType, 
     1147                       char _nBuddyIconHashType, const char *_szBuddyIconHash, 
     1148                       unsigned short nService); 
     1149}; 
     1150 
     1151class CPU_RequestService : public CPU_CommonFamily 
     1152{ 
     1153public: 
     1154  CPU_RequestService(unsigned short nFam); 
     1155}; 
     1156 
    11361157//-----AIMFetchAwayMessage-------------------------------------------------- 
    11371158class CPU_AIMFetchAwayMessage : public CPU_CommonFamily 
  • trunk/licq/include/licq_proxy.h

    r4714 r6181  
     1#ifndef PROXY_H 
     2#define PROXY_H 
     3 
    14#ifdef HAVE_CONFIG_H 
    25#include "config.h" 
     
    6972  bool HTTPOpenProxyConnection(const char *_szRemoteName, unsigned short _nRemotePort); 
    7073}; 
     74 
     75#endif 
  • trunk/licq/include/licq_socket.h

    r6164 r6181  
    167167  bool SendPacket(CBuffer *b); 
    168168  bool RecvPacket(); 
     169  bool ConnectTo(const char* server, unsigned short port, ProxyServer *xProxy); 
    169170}; 
    170171 
  • trunk/licq/include/licq_user.h

    r6165 r6181  
    516516  // Picture Info 
    517517  bool GetPicturePresent()              { return m_bPicturePresent; } 
     518  unsigned short BuddyIconType()    { return m_nBuddyIconType; } 
     519  char BuddyIconHashType()      { return m_nBuddyIconHashType; } 
     520  char *BuddyIconHash()         { return m_szBuddyIconHash; } 
     521  char *OurBuddyIconHash()      { return m_szOurBuddyIconHash; } 
    518522 
    519523  // Dynamic info fields for protocol plugins 
     
    635639  // Picture info 
    636640  void SetPicturePresent(bool b)      { m_bPicturePresent = b; SavePictureInfo(); } 
     641  void SetBuddyIconType(unsigned short s) { m_nBuddyIconType = s; } 
     642  void SetBuddyIconHashType(char s)   { m_nBuddyIconHashType = s; } 
     643  void SetBuddyIconHash(char *s)      { SetString(&m_szBuddyIconHash, s); } 
     644  void SetOurBuddyIconHash(char *s)   { SetString(&m_szOurBuddyIconHash, s); } 
    637645 
    638646  // Licq Info 
     
    946954  // Picture Info 
    947955  bool m_bPicturePresent; 
     956  unsigned short m_nBuddyIconType; 
     957  char m_nBuddyIconHashType; 
     958  char *m_szBuddyIconHash, *m_szOurBuddyIconHash; 
    948959 
    949960  // Dynamic info fields for protocol plugins 
  • trunk/licq/src/buffer.cpp

    r6165 r6181  
    324324  for (unsigned short i = 0; i < _nSize; i++) *this >> sz[i]; 
    325325  sz[_nSize] = '\0'; 
     326  return sz; 
     327} 
     328 
     329char *CBuffer::UnpackBinBlock(char *sz, unsigned short _nSize) 
     330{ 
     331  for (unsigned short i = 0; i < _nSize; i++) *this >> sz[i]; 
    326332  return sz; 
    327333} 
  • trunk/licq/src/icqd-srv.cpp

    r6180 r6181  
    2121#include <algorithm> 
    2222 
     23#include <boost/scoped_array.hpp> 
     24 
    2325// Localization 
    2426#include "gettext.h" 
     
    2830#include "licq_icqd.h" 
    2931#include "licq_translate.h" 
     32#include "licq_oscarservice.h" 
    3033#include "licq_packets.h" 
    3134#include "licq_socket.h" 
     
    717720} 
    718721 
     722//-----ProtoRequestPicture------------------------------------------------------ 
     723unsigned long CICQDaemon::ProtoRequestPicture(const char *_szId, unsigned long _nPPID) 
     724{ 
     725  unsigned long nRet = 0; 
     726 
     727  if (_nPPID == LICQ_PPID) 
     728  { 
     729    ICQUser *u = gUserManager.FetchUser(_szId, LICQ_PPID, LOCK_R); 
     730    if (u == NULL) return 0; 
     731 
     732    if (UseServerSideBuddyIcons() && strlen(u->BuddyIconHash()) > 0) 
     733    { 
     734      gUserManager.DropUser(u); 
     735      nRet = m_xBARTService->SendEvent(_szId, ICQ_SNACxBART_DOWNLOADxREQUEST, true); 
     736    } 
     737    else 
     738    { 
     739      bool bSendServer = (u->SocketDesc(ICQ_CHNxINFO) < 0); 
     740      gUserManager.DropUser(u); 
     741      nRet = icqRequestPicture(_szId, bSendServer); 
     742    } 
     743  } 
     744  else 
     745    PushProtoSignal(new CRequestPicture(_szId), _nPPID); 
     746   
     747  return nRet; 
     748} 
     749 
     750//-----icqRequestService-------------------------------------------------------- 
     751void CICQDaemon::icqRequestService(unsigned short nFam) 
     752{ 
     753  CPU_CommonFamily *p = new CPU_RequestService(nFam); 
     754  gLog.Info(tr("%sRequesting service socket for FAM 0x%02X (#%hu/#%d)...\n"), 
     755            L_SRVxSTR, nFam, p->Sequence(), p->SubSequence()); 
     756  SendEvent_Server(p); 
     757} 
     758 
    719759//-----icqSetStatus------------------------------------------------------------- 
    720760unsigned long CICQDaemon::ProtoSetStatus(unsigned long _nPPID, 
     
    17371777      case MAKESNAC(ICQ_SNACxFAM_LOCATION, ICQ_SNACxREQUESTxUSERxINFO): 
    17381778      case MAKESNAC(ICQ_SNACxFAM_LOCATION, ICQ_SNACxLOC_INFOxREQ): 
     1779      case MAKESNAC(ICQ_SNACxFAM_BART, ICQ_SNACxBART_DOWNLOADxREQUEST): 
    17391780        PushPluginEvent(e); 
    17401781        break; 
     
    18771918void CICQDaemon::postLogoff(int nSD, ICQEvent *cancelledEvent) 
    18781919{ 
     1920  if (m_xBARTService) 
     1921  { 
     1922    if (m_xBARTService->GetSocketDesc() != -1) 
     1923    { 
     1924      gSocketManager.CloseSocket(m_xBARTService->GetSocketDesc()); 
     1925      m_xBARTService->ResetSocket(); 
     1926      m_xBARTService->ChangeStatus(STATUS_UNINITIALIZED); 
     1927      m_xBARTService->ClearQueue(); 
     1928    } 
     1929  } 
    18791930  pthread_mutex_lock(&mutex_runningevents); 
    18801931  pthread_mutex_lock(&mutex_sendqueue_server); 
     
    20262077      return (-1); 
    20272078    } 
    2028     s->SetProxy(m_xProxy); 
    20292079  } 
    20302080  else if (m_xProxy != NULL) 
     
    20342084  } 
    20352085   
    2036   char ipbuf[32]; 
    2037  
    2038   if (m_xProxy == NULL) 
    2039   { 
    2040     gLog.Info(tr("%sResolving %s port %d...\n"), L_SRVxSTR, server, port); 
    2041     if (!s->SetRemoteAddr(server, port)) { 
    2042       char buf[128]; 
    2043       gLog.Warn(tr("%sUnable to resolve %s:\n%s%s.\n"), L_ERRORxSTR, 
    2044                 server, L_BLANKxSTR, s->ErrorStr(buf, 128)); 
    2045       delete s; 
    2046       return (-1); // no route to host (not connected) 
    2047     } 
    2048     gLog.Info(tr("%sICQ server found at %s:%d.\n"), L_SRVxSTR, 
    2049           s->RemoteIpStr(ipbuf), s->RemotePort()); 
    2050   } 
    2051   else 
    2052   { 
    2053     // It doesn't matter if it resolves or not, the proxy should do it then 
    2054     s->SetRemoteAddr(server, port); 
    2055   } 
    2056  
    2057   if (m_xProxy == NULL) 
    2058     gLog.Info(tr("%sOpening socket to server.\n"), L_SRVxSTR); 
    2059   else 
    2060     gLog.Info("%sOpening socket to server via proxy.\n", L_SRVxSTR); 
    2061   if (!s->OpenConnection()) 
    2062   { 
    2063     char buf[128]; 
    2064     gLog.Warn(tr("%sUnable to connect to %s:%d:\n%s%s.\n"), L_ERRORxSTR, 
    2065               s->RemoteIpStr(ipbuf), s->RemotePort(), L_BLANKxSTR, 
    2066               s->ErrorStr(buf, 128)); 
     2086  if (!s->ConnectTo(server, port, m_xProxy)) 
     2087  { 
    20672088    delete s; 
    20682089    return -1; 
     
    22222243  // each case to do the same thing. However, the individual case's may depend on the tlv 
    22232244  // coming to them, so leave this commented out for now and do some testing 
    2224   /* 
    22252245  if (snacFlags & 0x8000) 
    22262246  { 
    22272247    unsigned short bytes = packet.UnpackUnsignedShortBE(); 
    2228     unsigned short tlvCount = packet.UnpackUnsignedShortBE(); 
    2229     if (!packet.readTLV(tlvCount, bytes)) 
     2248    if (!packet.readTLV(-1, bytes)) 
    22302249    { 
    22312250      gLog.Error(tr("%sError parsing SNAC header\n"), L_SRVxSTR); 
     
    22332252    } 
    22342253  } 
    2235   */ 
    22362254 
    22372255  switch (nSubtype) 
    22382256  { 
    2239   case ICQ_SNACxSUB_READYxSERVER: 
     2257    case ICQ_SNACxSUB_READYxSERVER: 
    22402258    { 
    22412259      CSrvPacketTcp* p; 
     
    22582276    } 
    22592277 
    2260   case ICQ_SNACxSRV_ACKxIMxICQ: 
     2278    case ICQ_SNACxSUB_REDIRECT: 
     2279    { 
     2280      unsigned short nFam = 0; 
     2281 
     2282      if (!packet.readTLV()) 
     2283      { 
     2284        gLog.Warn(tr("%sError during parsing service redirect packet!\n"), L_WARNxSTR); 
     2285        break; 
     2286      } 
     2287      if (packet.getTLVLen(0x000D) == 2) 
     2288        nFam = packet.UnpackUnsignedShortTLV(0x000D); 
     2289 
     2290      gLog.Info(tr("%sRedirect for service 0x%02X received.\n"), L_SRVxSTR, nFam); 
     2291 
     2292      char *szServer = packet.UnpackStringTLV(0x0005); 
     2293      char *szCookie = packet.UnpackStringTLV(0x0006); 
     2294      unsigned short nCookieLen = packet.getTLVLen(0x0006); 
     2295      if (!szServer || !szCookie) 
     2296      { 
     2297        gLog.Warn(tr("%sInvalid servername (%s) or cookie (%s) in service redirect packet!\n"), 
     2298                  L_WARNxSTR, szServer ? szServer : "(null)", szCookie ? szCookie : "(null)"); 
     2299        if (szServer) delete [] szServer; 
     2300        if (szCookie) delete [] szCookie; 
     2301        break; 
     2302      } 
     2303 
     2304      char *szPort = strchr(szServer, ':'); 
     2305      unsigned short nPort; 
     2306      if (szPort) 
     2307      { 
     2308        *szPort++ = '\0'; 
     2309        nPort = atoi(szPort); 
     2310      } 
     2311      else 
     2312      { 
     2313        nPort = m_nICQServerPort; 
     2314      } 
     2315 
     2316      switch (nFam) 
     2317      { 
     2318        case ICQ_SNACxFAM_BART: 
     2319          if (m_xBARTService) 
     2320          { 
     2321            m_xBARTService->SetConnectCredential(szServer, nPort, szCookie, nCookieLen); 
     2322            m_xBARTService->ChangeStatus(STATUS_SERVICE_REQ_ACKED); 
     2323            break; 
     2324          } 
     2325          else 
     2326          { 
     2327            gLog.Warn(tr("%sService redirect packet for unallocated BART service.\n"), 
     2328                      L_WARNxSTR); 
     2329            break; 
     2330          } 
     2331 
     2332        default: 
     2333          gLog.Warn(tr("%sService redirect packet for unhandled service 0x%02X.\n"), 
     2334                    L_WARNxSTR, nFam); 
     2335      } 
     2336 
     2337      delete [] szServer; 
     2338      delete [] szCookie; 
     2339      break; 
     2340    } 
     2341 
     2342    case ICQ_SNACxSRV_ACKxIMxICQ: 
    22612343    { 
    22622344      // ICQOwner *o = gUserManager.FetchOwner(LICQ_PPID, LOCK_R); 
     
    22972379      break; 
    22982380    } 
    2299   case ICQ_SNACxSUB_RATE_INFO: 
    2300   { 
     2381 
     2382    case ICQ_SNACxSUB_RATE_INFO: 
     2383    { 
    23012384      gLog.Info(tr("%sServer sent us rate information.\n"), L_SRVxSTR); 
    23022385      CSrvPacketTcp *p = new CPU_RateAck(); 
     
    23202403  case ICQ_SNACxRCV_NAMExINFO: 
    23212404  { 
    2322     if (snacFlags & 0x8000) 
    2323     { 
    2324       unsigned short bytes = packet.UnpackUnsignedShortBE(); 
    2325       if (!packet.readTLV(-1, bytes)) 
    2326       { 
    2327         gLog.Error(tr("%sError parsing SNAC header\n"), L_SRVxSTR); 
    2328         return; 
    2329       } 
    2330     } 
    2331  
    23322405    unsigned short evil, tlvBlocks; 
    23332406    unsigned long nUin, realIP; 
     
    28692942    } 
    28702943 
     2944    if (packet.hasTLV(0x001d))  // Server-stored buddy icon information 
     2945    { 
     2946      CBuffer BART_info = packet.UnpackTLV(0x001d); 
     2947      unsigned short IconType = BART_info.UnpackUnsignedShortBE(); 
     2948      char HashType = BART_info.UnpackChar(); 
     2949      char HashLength = BART_info.UnpackChar(); 
     2950       
     2951      switch (IconType) 
     2952      { 
     2953        case BART_TYPExBUDDY_ICON_SMALL: 
     2954        case BART_TYPExBUDDY_ICON: 
     2955        { 
     2956          if (HashType == 1 && HashLength > 0 && HashLength <= 16) 
     2957          { 
     2958            boost::scoped_array<char> Hash(new char[HashLength]); 
     2959            boost::scoped_array<char> HashHex(new char[HashLength*2 + 1]); 
     2960             
     2961            BART_info.UnpackBinBlock(Hash.get(), HashLength); 
     2962            u->SetBuddyIconHash(PrintHex(HashHex.get(), Hash.get(), HashLength)); 
     2963            u->SetBuddyIconType(IconType); 
     2964            u->SetBuddyIconHashType(HashType); 
     2965            u->SavePictureInfo(); 
     2966          } 
     2967          break; 
     2968        } 
     2969 
     2970        default:    // Unsupported types of BART 
     2971          gLog.Warn(tr("%sUnsupported type 0x%02X of buddy icon for %s.\n"), 
     2972                    L_WARNxSTR, IconType, u->GetAlias()); 
     2973          break; 
     2974<