Changeset 6165

Show
Ignore:
Timestamp:
04/20/08 22:10:30 (8 months ago)
Author:
emostar
Message:

* Keep authorization when a user is moved to a new group.
* Add a new class to handle TLVs instead of a struct
* Add a TLVList to ICQUser
* Fix a few parts in the login sequence

Location:
trunk/licq
Files:
7 modified

Legend:

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

    r4526 r6165  
    11#ifndef LICQ_BUFFER_H 
    22#define LICQ_BUFFER_H 
     3 
     4#include <map> 
     5#include <vector> 
     6 
     7#include <boost/shared_array.hpp> 
     8#include <boost/shared_ptr.hpp> 
    39 
    410/*------------------------------------------------------------------------------ 
     
    2733extern void rev_e_long(unsigned long &); 
    2834 
    29 //=====TLV Structs ============================================================= 
    30 struct SOscarTLV 
     35//=====COscarTLV================================================================ 
     36class COscarTLV 
    3137{ 
    32   unsigned short nType; 
    33   unsigned short nLen; 
    34   unsigned char *pData; 
     38public: 
     39  COscarTLV(unsigned short type = 0, unsigned short length = 0, unsigned char *data = 0) : myType(type), myLen(length) 
     40  { 
     41    if (myLen > 0) 
     42    { 
     43      myData = boost::shared_array<unsigned char>(new  unsigned char[myLen]); 
     44      memcpy(myData.get(), data, myLen); 
     45    } 
     46  } 
     47 
     48  COscarTLV(const COscarTLV &c) 
     49  { 
     50    myType = c.myType; 
     51    myLen = c.myLen; 
     52    myData = boost::shared_array<unsigned char>(new unsigned char[c.myLen]); 
     53    memcpy(myData.get(), c.myData.get(), c.myLen); 
     54  } 
     55 
     56  unsigned short getType() const                     { return myType; } 
     57  unsigned short getLength() const                   { return myLen; } 
     58  boost::shared_array<unsigned char> getData() const { return myData; } 
     59 
     60  void setType(unsigned short type) { myType = type; } 
     61  void setData(unsigned char *data, unsigned short length) 
     62  { 
     63    if (length > 0) 
     64    { 
     65      myLen = length; 
     66      myData = boost::shared_array<unsigned char>(new unsigned char[length]); 
     67      memcpy(myData.get(), data, length); 
     68    } 
     69  } 
     70 
     71private: 
     72  unsigned short myType; 
     73  unsigned short myLen; 
     74  boost::shared_array<unsigned char> myData; 
     75 
     76friend class CBuffer; 
    3577}; 
    3678 
    37 struct SOscarTLV_Chain 
    38 { 
    39         SOscarTLV *pTLV; 
    40         SOscarTLV_Chain *pNext; 
    41 }; 
     79typedef boost::shared_ptr<COscarTLV> TLVPtr; 
     80typedef std::map<unsigned short, TLVPtr> TLVList; 
     81typedef TLVList::iterator TLVListIter; 
    4282 
    4383//=====CBuffer================================================================== 
     
    111151 
    112152   bool readTLV(int count = -1, int bytes = -1); // This should be called automatically if m_pTLV == 0 
    113    void cleanupTLV(); 
    114153 
    115154   void PackTLV(unsigned short, unsigned short, const char *); 
    116155   void PackTLV(unsigned short, unsigned short, CBuffer *); 
     156   void PackTLV(const TLVPtr&); 
    117157 
    118158   unsigned short getTLVLen(unsigned short); 
     
    123163   unsigned char UnpackCharTLV(unsigned short); 
    124164   char *UnpackStringTLV(unsigned short); // Need to delete[] returned string 
     165   //std::string UnpackStringTLV(unsigned short); 
    125166   CBuffer UnpackTLV(unsigned short); 
     167 
     168   TLVList getTLVList(); 
     169   TLVPtr getTLV(unsigned short _nType); 
    126170 
    127171private: 
     
    134178        *m_pDataPosRead; 
    135179   unsigned long m_nDataSize; 
    136    SOscarTLV_Chain *m_pTLV; 
     180   TLVList myTLVs; 
    137181 
    138    SOscarTLV *getTLV(unsigned short _nType); 
    139182   void antiwarning() { NetworkIpToPacketIp(PacketIpToNetworkIp(127)); } 
    140183}; 
  • trunk/licq/include/licq_packets.h

    r5972 r6165  
    309309}; 
    310310 
     311//-----ListRequestRights----------------------------------------------------- 
     312class CPU_ListRequestRights : public CPU_CommonFamily 
     313{ 
     314public: 
     315  CPU_ListRequestRights(); 
     316}; 
     317 
    311318//-----ImICQ------------------------------------------------------------------ 
    312319class CPU_ImICQ : public CPU_CommonFamily 
  • trunk/licq/include/licq_user.h

    r6047 r6165  
    780780  char *PortStr(char *rbuf); 
    781781 
     782  // User TLV List handling 
     783  void AddTLV(TLVPtr); 
     784  void RemoveTLV(unsigned long); 
     785  TLVList GetTLVList(); 
     786 
    782787  // Don't call these: 
    783788  int SocketDesc(unsigned char); 
     
    953958  unsigned short m_nGSID; 
    954959 
     960  // Extra TLVs attached to this user's SSI info 
     961  // We use a map to allow fast access to the TLV by type, even though the 
     962  // actual type is in SOscarTLV as well. Which should make it obvious 
     963  // that the TLV handling should be fixed in licq_buffer.h/buffer.cpp 
     964  TLVList myTLVs; 
     965 
    955966  UserEventList m_vcMessages; 
    956967 
  • trunk/licq/src/buffer.cpp

    r4951 r6165  
    174174{ 
    175175  m_pDataStart = m_pDataPosRead = m_pDataPosWrite = NULL; 
    176   m_pTLV = NULL; 
    177176  m_nDataSize = 0; 
    178177} 
     
    181180CBuffer::CBuffer(unsigned long _nDataSize) 
    182181{ 
    183   m_pTLV = NULL; 
    184182  m_nDataSize = _nDataSize; 
    185183  if (_nDataSize) 
     
    204202  m_pDataPosRead = m_pDataStart + (b.getDataPosRead() - b.getDataStart()); 
    205203  m_pDataPosWrite = m_pDataStart + (b.getDataPosWrite() - b.getDataStart()); 
    206   // DAW FIXME 
    207   m_pTLV = NULL; 
    208204} 
    209205 
     
    214210  { 
    215211     m_pDataStart = m_pDataPosRead = m_pDataPosWrite = NULL; 
    216      m_pTLV = NULL; 
    217212     m_nDataSize = 0; 
    218213  } 
    219214  else 
    220215  { 
    221     m_pTLV = NULL; 
    222216    m_nDataSize = b->getDataMaxSize(); 
    223217    m_pDataStart = new char[m_nDataSize]; 
     
    242236   m_pDataPosRead = m_pDataStart + (b.getDataPosRead() - b.getDataStart()); 
    243237   m_pDataPosWrite = m_pDataStart + (b.getDataPosWrite() - b.getDataStart()); 
    244    m_pTLV = NULL; 
     238   myTLVs = b.myTLVs; 
    245239 
    246240   return (*this); 
     
    275269   m_pDataStart = new char[m_nDataSize]; 
    276270   m_pDataPosRead = m_pDataPosWrite = m_pDataStart; 
    277    m_pTLV = NULL; 
    278271} 
    279272 
     
    462455{ 
    463456  if (m_pDataStart != NULL) delete[] m_pDataStart; 
    464   if (m_pTLV) cleanupTLV(); 
    465   m_pTLV = NULL; 
     457  myTLVs.clear(); 
    466458  m_pDataStart = m_pDataPosRead = m_pDataPosWrite = NULL; 
    467459  m_nDataSize = 0; 
     
    499491{ 
    500492  if (m_pDataStart != NULL) delete[] m_pDataStart; 
    501   if (m_pTLV) cleanupTLV(); 
    502493} 
    503494 
     
    630621bool CBuffer::readTLV(int nCount, int nBytes) 
    631622{ 
    632   if (m_pTLV || !nCount) return false; // already have one 
     623  if (!nCount) return false; 
     624 
     625  // Clear the list if we already have some TLVs 
     626  if (myTLVs.size() > 0) 
     627    myTLVs.clear(); 
    633628 
    634629  int num = 0; 
    635630  int nCurBytes = 0; 
    636631 
     632  // Keep reading until it is impossible for any TLV headers to be found 
    637633  while(getDataPosRead() + 4 < (getDataStart() + getDataSize())) { 
    638     SOscarTLV_Chain *now = new SOscarTLV_Chain; 
    639     now->pTLV = new SOscarTLV; 
    640  
    641     *this >> now->pTLV->nType; 
    642     *this >> now->pTLV->nLen; 
    643  
    644     rev_e_short(now->pTLV->nType); 
    645     rev_e_short(now->pTLV->nLen); 
    646  
    647     nCurBytes += 4 + now->pTLV->nLen; 
    648  
    649     if(getDataPosRead() + now->pTLV->nLen > (getDataStart() + getDataSize()) || 
    650        now->pTLV->nLen < 1) { 
    651       now->pTLV->nLen = 0; 
    652       now->pTLV->pData = 0; 
     634    TLVPtr tlv(new COscarTLV); 
     635 
     636    *this >> tlv->myType; 
     637    *this >> tlv->myLen; 
     638 
     639    rev_e_short(tlv->myType); 
     640    rev_e_short(tlv->myLen); 
     641 
     642    nCurBytes += 4 + tlv->myLen; 
     643 
     644    if(getDataPosRead() + tlv->myLen > (getDataStart() + getDataSize()) || 
     645       tlv->myLen < 1) { 
     646      tlv->myLen = 0; 
    653647    } 
    654648    else { 
    655       now->pTLV->pData = new unsigned char[now->pTLV->nLen]; 
    656       memcpy(now->pTLV->pData, m_pDataPosRead, now->pTLV->nLen); 
    657       m_pDataPosRead += now->pTLV->nLen; 
     649      tlv->myData.reset(new unsigned char[tlv->myLen]); 
     650      memcpy(tlv->myData.get(), m_pDataPosRead, tlv->myLen); 
     651      m_pDataPosRead += tlv->myLen; 
    658652    } 
    659653 
    660     now->pNext = m_pTLV; 
    661     m_pTLV = now; 
     654    // Save it in the map 
     655    myTLVs[tlv->myType] = tlv; 
    662656 
    663657    ++num; 
    664     if (nCount > 0 && num == nCount) 
    665       return true; 
    666  
    667     if (nBytes > 0 && nCurBytes == nBytes) 
     658    if ((nCount > 0 && num == nCount) || 
     659        (nBytes > 0 && nCurBytes == nBytes) ) 
    668660      return true; 
    669661 
     
    686678} 
    687679 
    688 void CBuffer::cleanupTLV() 
    689 { 
    690   if (!m_pTLV) return; 
    691  
    692   SOscarTLV_Chain *now = m_pTLV; 
    693  
    694   while (now) { 
    695     SOscarTLV_Chain *tmp; 
    696  
    697     if (now->pTLV) 
    698     { 
    699       if (now->pTLV->pData) 
    700     delete [] now->pTLV->pData; 
    701  
    702       delete now->pTLV; 
    703     } 
    704  
    705     tmp = now->pNext; 
    706     delete now; 
    707     now = tmp; 
    708   } 
    709  
    710   m_pTLV = NULL; 
    711 } 
    712  
    713680void CBuffer::PackTLV(unsigned short nType, unsigned short nSize, 
    714681               const char *data) 
     
    725692  PackUnsignedShortBE(nSize); 
    726693  Pack(b); 
     694} 
     695 
     696void CBuffer::PackTLV(const TLVPtr& tlv) 
     697{ 
     698  PackUnsignedShortBE(tlv->myType); 
     699  PackUnsignedShortBE(tlv->myLen); 
     700  Pack(reinterpret_cast<const char *>(tlv->myData.get()), tlv->myLen); 
    727701} 
    728702 
     
    741715unsigned short CBuffer::getTLVLen(unsigned short nType) 
    742716{ 
    743   SOscarTLV *pTLV = getTLV(nType); 
    744   if (pTLV) 
    745     return pTLV->nLen; 
    746  
    747   return 0; 
     717  unsigned short len = 0; 
     718  TLVListIter iter = myTLVs.find(nType); 
     719  if (iter != myTLVs.end()) 
     720    len = iter->second->myLen; 
     721  return len; 
    748722} 
    749723 
    750724bool CBuffer::hasTLV(unsigned short nType) 
    751725{ 
    752   bool bRet = false; 
    753   SOscarTLV *pTLV = getTLV(nType); 
    754   if (pTLV) 
    755     bRet = true; 
    756  
    757   return bRet; 
     726  TLVListIter iter = myTLVs.find(nType); 
     727  bool found = (iter != myTLVs.end()); 
     728  return found; 
    758729} 
    759730 
     
    762733  unsigned long nRet = 0; 
    763734 
    764   SOscarTLV *pTLV = getTLV(nType); 
    765   if (pTLV && pTLV->nLen > 3) 
    766   { 
    767     nRet |= (*((pTLV->pData)+0) << 24); 
    768     nRet |= (*((pTLV->pData)+1) << 16); 
    769     nRet |= (*((pTLV->pData)+2) << 8); 
    770     nRet |= (*((pTLV->pData)+3)); 
     735  try 
     736  { 
     737    TLVPtr tlv = getTLV(nType); 
     738    if (tlv->myLen > 3) 
     739    { 
     740      nRet |= (*((tlv->myData.get())+0) << 24); 
     741      nRet |= (*((tlv->myData.get())+1) << 16); 
     742      nRet |= (*((tlv->myData.get())+2) << 8); 
     743      nRet |= (*((tlv->myData.get())+3)); 
     744    } 
     745  } 
     746  catch (...) 
     747  { 
     748    // TODO Throw an exception 
    771749  } 
    772750 
     
    778756  unsigned short nRet = 0; 
    779757 
    780   SOscarTLV *pTLV = getTLV(nType); 
    781   if (pTLV && pTLV->nLen > 1) 
    782   { 
    783     nRet |= (*((pTLV->pData)+0) << 8); 
    784     nRet |= (*((pTLV->pData)+1)); 
     758  try 
     759  { 
     760    TLVPtr tlv = getTLV(nType); 
     761    if (tlv->myLen > 1) 
     762    { 
     763      nRet |= (*((tlv->myData.get())+0) << 8); 
     764      nRet |= (*((tlv->myData.get())+1)); 
     765    } 
     766  } 
     767  catch (...) 
     768  { 
     769    // TODO Throw an exception 
    785770  } 
    786771 
     
    792777  unsigned char nRet = 0; 
    793778 
    794   SOscarTLV *pTLV = getTLV(nType); 
    795   if (pTLV && pTLV->nLen > 0) 
    796     nRet = *(pTLV->pData); 
     779  try 
     780  { 
     781    TLVPtr tlv = getTLV(nType); 
     782    if (tlv->myLen > 0) 
     783      nRet = *(tlv->myData.get()); 
     784  } 
     785  catch (...) 
     786  { 
     787    // TODO Throw an exception 
     788  } 
    797789 
    798790  return nRet; 
     
    804796  char *str = 0; 
    805797 
    806   SOscarTLV *pTLV = getTLV(nType); 
    807   if (pTLV) 
    808   { 
    809     str = new char[pTLV->nLen+1]; 
    810     if (!str) return 0; 
    811  
    812     memcpy(str, pTLV->pData, pTLV->nLen); 
    813     *(str+pTLV->nLen) = '\0'; 
     798  try 
     799  { 
     800    TLVPtr tlv = getTLV(nType); 
     801    str = new char[tlv->myLen+1]; 
     802    memcpy(str, tlv->myData.get(), tlv->myLen); 
     803    *(str+tlv->myLen) = '\0'; 
     804  } 
     805  catch (...) 
     806  { 
     807    if (str) 
     808    { 
     809      delete [] str; 
     810      str = 0; 
     811    } 
    814812  } 
    815813 
     
    817815} 
    818816 
     817#if 0 
     818//TODO Add this function and use it everywhere so we don't have to 
     819// constanly remember to call delete[] 
     820std::string CBuffer::UnpackStringTLV(unsigned short nType) 
     821{ 
     822  std::string str; 
     823 
     824  try 
     825  { 
     826    TLVPtr tlv = getTLV(nType); 
     827    str.assign(tlv->myData.get(), tlv->myLen); 
     828  } 
     829  catch (...) 
     830  { 
     831    // TODO Throw an exception 
     832  } 
     833 
     834  return str; 
     835} 
     836#endif 
     837 
    819838CBuffer CBuffer::UnpackTLV(unsigned short nType) 
    820839{ 
    821   SOscarTLV *pTLV = getTLV(nType); 
    822   if (pTLV) 
    823   { 
    824     CBuffer cbuf(pTLV->nLen); 
    825     cbuf.Pack((const char*)pTLV->pData, pTLV->nLen); 
     840  try 
     841  { 
     842    TLVPtr tlv = getTLV(nType); 
     843    CBuffer cbuf(tlv->myLen); 
     844    cbuf.Pack(reinterpret_cast<const char *>(tlv->myData.get()), tlv->myLen); 
    826845    cbuf.Reset(); 
    827846 
    828847    return cbuf; 
    829848  } 
    830   else 
     849  catch (...) 
     850  { 
    831851    return CBuffer(0); 
    832 } 
    833  
    834 SOscarTLV *CBuffer::getTLV(unsigned short nType) 
    835 { 
    836   if (!m_pTLV) return 0; 
    837  
    838   SOscarTLV_Chain *now; 
    839  
    840   for (now = m_pTLV; now; now = now->pNext) 
    841     if (now && now->pTLV && now->pTLV->nType == nType) 
    842         return now->pTLV; 
    843  
    844   return 0; 
     852  } 
     853} 
     854 
     855TLVPtr CBuffer::getTLV(unsigned short nType) 
     856{ 
     857  if (myTLVs.size() == 0) 
     858    throw std::exception(); 
     859 
     860  TLVListIter iter = myTLVs.find(nType); 
     861  if (iter == myTLVs.end()) 
     862    throw std::exception(); 
     863 
     864  return iter->second; 
     865} 
     866 
     867TLVList CBuffer::getTLVList() 
     868{ 
     869  return myTLVs; 
    845870} 
    846871 
  • trunk/licq/src/icqd-srv.cpp

    r6137 r6165  
    22162216void CICQDaemon::ProcessServiceFam(CBuffer &packet, unsigned short nSubtype) 
    22172217{ 
    2218   packet.UnpackUnsignedShortBE(); // flags 
     2218  unsigned short snacFlags = packet.UnpackUnsignedShortBE(); // flags 
    22192219  packet.UnpackUnsignedLongBE(); // sequence 
     2220 
     2221  // TODO The TLVs should be processed first, in a common area, instead of requiring 
     2222  // each case to do the same thing. However, the individual case's may depend on the tlv 
     2223  // coming to them, so leave this commented out for now and do some testing 
     2224  /* 
     2225  if (snacFlags & 0x8000) 
     2226  { 
     2227    unsigned short bytes = packet.UnpackUnsignedShortBE(); 
     2228    unsigned short tlvCount = packet.UnpackUnsignedShortBE(); 
     2229    if (!packet.readTLV(tlvCount, bytes)) 
     2230    { 
     2231      gLog.Error(tr("%sError parsing SNAC header\n"), L_SRVxSTR); 
     2232      return; 
     2233    } 
     2234  } 
     2235  */ 
    22202236 
    22212237  switch (nSubtype) 
     
    22562272 
    22572273      gLog.Info(tr("%sRequesting list rights.\n"), L_SRVxSTR); 
    2258       p = new CPU_GenericFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_REQUESTxRIGHTS); 
     2274      p = new CPU_ListRequestRights(); 
     2275      SendExpectEvent_Server(0, p, NULL); 
     2276 
     2277      gLog.Info(tr("%sRequesting roster rights.\n"), L_SRVxSTR); 
     2278      p = new CPU_RequestList(); 
    22592279      SendEvent_Server(p); 
    2260  
    2261       gLog.Info(tr("%sRequesting list.\n"), L_SRVxSTR); 
    2262       p = new CPU_RequestList(); 
    2263       SendExpectEvent_Server(0, p, NULL); 
    22642280 
    22652281      gLog.Info(tr("%sRequesting location rights.\n"), L_SRVxSTR); 
     
    23042320  case ICQ_SNACxRCV_NAMExINFO: 
    23052321  { 
    2306     unsigned short nUserClass, nLevel; 
     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 
     2332    unsigned short evil, tlvBlocks; 
    23072333    unsigned long nUin, realIP; 
    23082334    time_t nOnlineSince = 0; 
     
    23112337 
    23122338    nUin = packet.UnpackUinString(); 
    2313     nLevel = packet.UnpackUnsignedShortBE(); 
    2314     nUserClass = packet.UnpackUnsignedShortBE(); 
    2315  
    2316     gLog.Info("%sUIN: %lu level: %04hx Class: %04hx\n", L_SRVxSTR, 
    2317               nUin, nLevel, nUserClass ); 
    2318  
    2319     if (!packet.readTLV()) { 
     2339    evil = packet.UnpackUnsignedShortBE(); 
     2340    tlvBlocks = packet.UnpackUnsignedShortBE(); 
     2341 
     2342    gLog.Info("%sUIN: %lu Evil: %04hx\n", L_SRVxSTR, nUin, evil); 
     2343 
     2344    if (!packet.readTLV(tlvBlocks)) { 
    23202345      char *buf; 
    23212346      gLog.Unknown(tr("%sUnknown server response:\n%s\n"), L_UNKNOWNxSTR, 
     
    39593984  unsigned long nSubSequence = packet.UnpackUnsignedLongBE(); 
    39603985 
    3961   // First 8 bytes - unknown 
    3962   if (nSubtype != ICQ_SNACxLIST_ROSTxREPLY) 
    3963   { 
    3964     packet.UnpackUnsignedLong(); 
    3965     packet.UnpackUnsignedLong(); 
    3966   }  
     3986  if (nFlags & 0x8000) 
     3987  { 
     3988    unsigned short bytes = packet.UnpackUnsignedShortBE(); 
     3989    if (!packet.readTLV(-1, bytes)) 
     3990    { 
     3991      gLog.Error(tr("%sError parsing SNAC header\n"), L_SRVxSTR); 
     3992      return; 
     3993    } 
     3994  } 
    39673995 
    39683996  switch (nSubtype) 
     
    39974025        if (e == NULL) 
    39984026        { 
    3999           gLog.Warn(tr("%sContact list without request.\n"), L_SRVxSTR); 
     4027          // Try acking it, even if we didn't expect it 
     4028          //gLog.Warn(tr("%sContact list without request.\n"), L_SRVxSTR); 
     4029          gLog.Info(tr("%sActivate server contact list.\n"), L_SRVxSTR); 
     4030          CSrvPacketTcp *p = new CPU_GenericFamily(ICQ_SNACxFAM_LIST, ICQ_SNACxLIST_ROSTxACK); 
     4031          SendEvent_Server(p); 
    40004032          break; 
    40014033        } 
     
    40694101            if (u) 
    40704102            { 
     4103              // For now, just save all the TLVs. We should change this to have awaiting auth check 
     4104              // for the 0x0066 TLV, SMS number if it has the 0x013A TLV, etc 
     4105              TLVList tlvList = packet.getTLVList(); 
     4106              TLVListIter iter; 
     4107              for (iter = tlvList.begin(); iter != tlvList.end(); ++iter) 
     4108              { 
     4109                TLVPtr tlv = iter->second; 
     4110                u->AddTLV(tlv); 
     4111              } 
     4112 
    40714113              u->SetGSID(nTag); 
    40724114 
     
    41934235          delete [] szUnicodeName; 
    41944236 
    4195         packet.cleanupTLV(); 
    41964237        if (szId) 
    41974238          delete[] szId; 
     
    42194260      break; 
    42204261    } // case rost reply 
     4262 
     4263    case ICQ_SNACxLIST_ROSTxUPD_GROUP: 
     4264    { 
     4265      gLog.Info(tr("%sReceived updated contact information from server.\n"), L_SRVxSTR); 
     4266 
     4267      char *szId = packet.UnpackStringBE(); 
     4268      if (szId == 0) 
     4269      { 
     4270        gLog.Error(tr("%sDid not receive user ID.\n"), L_SRVxSTR); 
     4271        break; 
     4272      } 
     4273 
     4274      unsigned short gsid    = packet.UnpackUnsignedShortBE(); 
     4275      unsigned short sid     = packet.UnpackUnsignedShortBE(); 
     4276      /*unsigned short classid =*/ packet.UnpackUnsignedShortBE(); 
     4277 
     4278      unsigned short tlvBytes = packet.UnpackUnsignedShortBE(); 
     4279 
     4280      if (!packet.readTLV(-1, tlvBytes)) 
     4281      { 
     4282        gLog.Error(tr("%sError during parsing packet!\n"), L_ERRORxSTR); 
     4283        break; 
     4284      } 
     4285 
     4286      ICQUser *u = gUserManager.FetchUser(szId, LICQ_PPID, LOCK_W); 
     4287      if (u) 
     4288      { 
     4289        // First update their gsid/sid 
     4290        u->SetSID(sid); 
     4291        u->SetGSID(gsid); 
     4292 
     4293        // Now the the tlv of attributes to attach to the user 
     4294        TLVList tlvList = packet.getTLVList(); 
     4295        TLVListIter iter; 
     4296        for (iter = tlvList.begin(); iter != tlvList.end(); ++iter) 
     4297        { 
     4298          TLVPtr tlv = iter->second; 
     4299          u->AddTLV(tlv); 
     4300        } 
     4301 
     4302        gUserManager.DropUser(u); 
     4303      } 
     4304 
     4305      delete [] szId; 
     4306 
     4307      break; 
     4308    } 
    42214309 
    42224310    case ICQ_SNACxLIST_ROSTxSYNCED: 
     
    44664554         { 
    44674555           u->SetAwaitingAuth(false); 
     4556           u->RemoveTLV(0x0066); 
    44684557           gUserManager.DropUser(u); 
    44694558         }