On Tuesday 23 April 2002 11:52, Pletyak Attila wrote:
<snip>
>       As I've a quite big contact list what I do not want to add again
> one-by-one (or with editing the users.conf file), I would like to ask
> whether the server side list storage will be implemented in the near
> future.

I am attaching an "embryonic" patch that add support to the server side 
list retrival.
Why? 
because i won't have any spare time in the nexts days or week and may be 
someone want to play with it or import his/her list.

I am planing finishing the patch and add the full support of the server 
side list (add,remove, store groups, ...) if nobody finish it before or if 
licq developers complain. if you want to add something in the meanwhile 
just  do it :) 

So...This patch gets the list from server and prints it to the standar 
error fd. nothing else. if you want to disable it just comment line 1024 
in srv/icqd-srv.cpp...and yes..that line will be moved to other place i 
guess. It's not a patch for dayly use....

Also, i think that is a good time to start the discussion of how the server 
side list storage (ssld) feature will be integrated to the rest of the 
licq.

i added another file to the src/ directory: fam_lists.cpp that handle the 
packets of the lists snac family. i did this because i think that 
icqd-srv.cpp is too crowded.

It would be nice that some one test it with a big list: i just used 
lite.icq.com and added only 3 contacts, and i didn't recive all the range 
of features of the list.

How to patch?
cd 
cvs -z3 -d:pserver:[EMAIL PROTECTED]:/cvsroot/licq co licq
cd licq
patch -p0 < ../slists_1.diff
cp ../fam_lists.cpp src
...
(remember to recomplile qt)

This is an example of what i am getting. (set DEBUG level to all if you 
want to see the packet)(where X is a number of the uin and x is a letter 
of the nickname)

    --------0-------
    Group ID: 23550
    Group ID: 19426
    Group ID: 25661
    Group ID: 27527
    --------1-------
    Visibily setting: Block only users in the invisible list from seeing us
    --------2-------
    ICQTIC (do you know the meaning?)
    TAG = 0
    ID  = 2892
    NP  = 1
    TLV = 3610,0,0,0
    --------3-------
    Group: GID: 19426 G#: 512 Name: Family
    --------4-------
     UIN: XXXXXXX NAME: 'Juam' ID: 2 GROUPID 19426 (Normal)
    --------5-------
    Group: GID: 23550 G#: 20272 Name: General
    --------6-------
     UIN: XXXXXXX NAME: 'xxxx' ID: 12367 GROUPID 23550 (Normal)
    --------7-------
    Group: GID: 25661 G#: 768 Name: Friends
    --------8-------
     UIN: XXXXXXXXX NAME: 'xxxxxxxx' ID: 3 GROUPID 25661 (Normal)(Waiting 
auth)
    --------9-------
    Group: GID: 27527 G#: 28483 Name: Co-Workers
    time_t = Wed Apr 24 07:19:27 2002

Now parse this to get a new user.conf is trivial :)

Hell...this email got big :)
Well.- i am waiting a reply.
Regards,
        Juan.

-- 
Buenos Aires, Argentina

Index: include/licq_buffer.h
===================================================================
RCS file: /cvsroot/licq/licq/include/licq_buffer.h,v
retrieving revision 1.5
diff -u -1 -b -p -r1.5 licq_buffer.h
--- include/licq_buffer.h	23 Jan 2002 07:04:11 -0000	1.5
+++ include/licq_buffer.h	25 Apr 2002 00:09:02 -0000
@@ -25,2 +25,7 @@ extern unsigned long NetworkIpToPacketIp
 
+
+/* little indian 2 big endian shorts
+ */ 
+extern unsigned short get_be_short(char *p);
+
 extern void rev_e_short(unsigned short &);
@@ -89,2 +94,3 @@ public:
    char *UnpackStringBE(char *);
+   char *UnpackStringBE();
    unsigned long UnpackUnsignedLong();
Index: include/licq_icq.h
===================================================================
RCS file: /cvsroot/licq/licq/include/licq_icq.h,v
retrieving revision 1.21
diff -u -1 -b -p -r1.21 licq_icq.h
--- include/licq_icq.h	8 Apr 2002 16:09:14 -0000	1.21
+++ include/licq_icq.h	25 Apr 2002 00:09:02 -0000
@@ -82,2 +82,18 @@ const unsigned short ICQ_SNACxBOS_REMxIN
 
+// Subtypes for Lists family
+// from Massimo Melina protocol notes (www.rejetto.com/icq)
+// and  stricq (www.stricq.com/icqv8/Command_view.cfm)
+const unsigned short ICQ_SNACxLISTS_REQUESTxRIGHTS  = 0x0002; // client
+const unsigned short ICQ_SNACxLISTS_RIGHTSxGRANTED  = 0x0003; // server
+const unsigned short ICQ_SNACxLISTS_REQUESTxROSTER2 = 0x0004; // server
+const unsigned short ICQ_SNACxLISTS_REQUESTxROSTER  = 0x0005; // client 
+const unsigned short ICQ_SNACxLISTS_ROSTERxREPLY    = 0x0006; // server
+const unsigned short ICQ_SNACxLISTS_ROSTERxACK	    = 0x0007; // client
+const unsigned short ICQ_SNACxLISTS_ADDxVISIBLExLIST= 0x0008; // client
+const unsigned short ICQ_SNACxLISTS_UPDATExGROUP    = 0x0009; // client
+const unsigned short ICQ_SNACxLISTS_REMOVExVISIBLExLIST=0x000A; // client
+const unsigned short ICQ_SNACxLISTS_REMOVEXACK	    = 0x000E; // server
+const unsigned short ICQ_SNACxLISTS_AUTHxREQUEST2   = 0x0014; // client
+const unsigned short ICQ_SNACxLISTS_AUTHxREQUEST    = 0x0018; // client
+
 // Subtypes for various family
Index: include/licq_icqd.h
===================================================================
RCS file: /cvsroot/licq/licq/include/licq_icqd.h,v
retrieving revision 1.27
diff -u -1 -b -p -r1.27 licq_icqd.h
--- include/licq_icqd.h	16 Apr 2002 13:33:01 -0000	1.27
+++ include/licq_icqd.h	25 Apr 2002 00:09:03 -0000
@@ -382,2 +382,3 @@ protected:
   void ProcessBOSFam(CBuffer&, unsigned short);
+  void ProcessListsFam( CBuffer &, unsigned short);
   void ProcessNewUINFam(CBuffer &, unsigned short);
Index: include/licq_packets.h
===================================================================
RCS file: /cvsroot/licq/licq/include/licq_packets.h,v
retrieving revision 1.23
diff -u -1 -b -p -r1.23 licq_packets.h
--- include/licq_packets.h	16 Apr 2002 13:34:37 -0000	1.23
+++ include/licq_packets.h	25 Apr 2002 00:09:03 -0000
@@ -263,3 +263,11 @@ public:
 };
-
+//-----RequesterverList------------------------------------------------------
+class CPU_RequestServerList : public CPU_GenericFamily
+{
+	public:
+	 CPU_RequestServerList( time_t saved_time, unsigned short nrecords);
+	protected:
+	 time_t saved_time;
+	 unsigned short nrcords;
+};
 //-----SetStatus----------------------------------------------------------------
@@ -714,3 +722,2 @@ protected:
 };
-
 
Index: include/licq_user.h
===================================================================
RCS file: /cvsroot/licq/licq/include/licq_user.h,v
retrieving revision 1.23
diff -u -1 -b -p -r1.23 licq_user.h
--- include/licq_user.h	20 Mar 2002 06:35:46 -0000	1.23
+++ include/licq_user.h	25 Apr 2002 00:09:03 -0000
@@ -214,2 +214,3 @@ public:
   // Licq Info
+  unsigned short GetSID()		{ return m_nSID; }
   char *AutoResponse()                  { return m_szAutoResponse; }
@@ -248,2 +249,4 @@ public:
 
+  
+
   // General Info
@@ -296,2 +299,3 @@ public:
   // Licq Info
+  void SetSID(unsigned short id)	{ m_nSID = id; }
   void SetEnableSave(bool s)          { if (m_bOnContactList) m_bEnableSave = s; }
@@ -447,2 +451,3 @@ protected:
                 m_nGroups[2];
+  unsigned short sid;
   char m_nMode;
@@ -506,2 +511,5 @@ protected:
 
+  // server side id
+  unsigned short m_nSID;
+
   UserEventList m_vcMessages;
@@ -541,2 +549,8 @@ public:
 
+  // Server side functions
+  time_t GetSSCheck()		{ return m_nSStime; }
+  void   SetSSCheck( time_t t)	{ m_nSStime = t ;}
+  unsigned short GetSSCount()	{ return m_nSScount; }
+  void SetSSCount(unsigned short c)	{ m_nSScount = c;}
+
   // Virtual overloaded functions
@@ -552,2 +566,4 @@ protected:
   unsigned long m_nRandomChatGroup;
+  time_t m_nSStime;
+  unsigned short m_nSScount;
 };
Index: src/Makefile.am
===================================================================
RCS file: /cvsroot/licq/licq/src/Makefile.am,v
retrieving revision 1.15
diff -u -1 -b -p -r1.15 Makefile.am
--- src/Makefile.am	17 Mar 2002 05:47:55 -0000	1.15
+++ src/Makefile.am	25 Apr 2002 00:09:04 -0000
@@ -17,3 +17,3 @@ licq_SOURCES = licq.cpp main.cpp \
          icqd-chat.cpp sighandler.c icqd-filetransfer.cpp \
-         hebrev.c icqcolor.cpp
+         hebrev.c icqcolor.cpp fam_lists.cpp
 
Index: src/buffer.cpp
===================================================================
RCS file: /cvsroot/licq/licq/src/buffer.cpp,v
retrieving revision 1.11
diff -u -1 -b -p -r1.11 buffer.cpp
--- src/buffer.cpp	20 Mar 2002 16:00:53 -0000	1.11
+++ src/buffer.cpp	25 Apr 2002 00:09:04 -0000
@@ -301,2 +301,15 @@ CBuffer& CBuffer::operator>>(unsigned lo
 
+char *CBuffer::UnpackStringBE()
+{
+  unsigned short nLen;
+  *this >> nLen;
+  nLen = get_be_short( (char *) &nLen );
+  char* sz = new char[nLen+1];
+  sz[0] = '\0';
+  for (unsigned short i = 0; i < nLen; i++) *this >> sz[i];
+     sz[nLen] = '\0';
+
+  return sz;
+}
+
 char *CBuffer::UnpackStringBE(char* sz)
Index: src/icqd-srv.cpp
===================================================================
RCS file: /cvsroot/licq/licq/src/icqd-srv.cpp,v
retrieving revision 1.30
diff -u -1 -b -p -r1.30 icqd-srv.cpp
--- src/icqd-srv.cpp	16 Apr 2002 13:37:36 -0000	1.30
+++ src/icqd-srv.cpp	25 Apr 2002 00:09:05 -0000
@@ -1014,2 +1014,16 @@ void CICQDaemon::ProcessServiceFam(CBuff
 
+      // SS List. 
+      ICQOwner *o = gUserManager.FetchOwner(LOCK_R);
+      gLog.Info("%sRequesting %s Server Contact List rights.\n",L_SRVxSTR,
+      		(o->GetSSCheck() && o->GetSSCount()) ? "Partial":"Complete"); 
+
+     /* if( o->GetSSCheck() && o->GetSSCount() )
+      *	p = new CPU_RequestServerList( o->GetSSCheck(),o->GetSSCount());
+      *else
+      */
+      	p = new CPU_GenericFamily(ICQ_SNACxFAM_LISTS,
+      				ICQ_SNACxLISTS_REQUESTxRIGHTS);
+      gUserManager.DropOwner();
+      SendEvent_Server(p);
+      
       gLog.Info("%sRequesting Instant Messaging rights.\n", L_SRVxSTR);
@@ -1022,2 +1036,3 @@ void CICQDaemon::ProcessServiceFam(CBuff
 
+      
       break;
@@ -2599,2 +2614,6 @@ void CICQDaemon::ProcessDataChannel(CBuf
     ProcessMessageFam(packet, nSubtype);
+    break;
+
+  case ICQ_SNACxFAM_LISTS:
+    ProcessListsFam(packet, nSubtype);
     break;
Index: src/icqpacket.cpp
===================================================================
RCS file: /cvsroot/licq/licq/src/icqpacket.cpp,v
retrieving revision 1.37
diff -u -1 -b -p -r1.37 icqpacket.cpp
--- src/icqpacket.cpp	16 Apr 2002 13:38:33 -0000	1.37
+++ src/icqpacket.cpp	25 Apr 2002 00:09:06 -0000
@@ -900,2 +900,13 @@ CPU_GenericUinList::CPU_GenericUinList(u
 
+//----RequestServerList-------------------------------------------------------
+CPU_RequestServerList::CPU_RequestServerList( time_t saved_time,
+						unsigned short nrecords)
+  : CPU_GenericFamily(ICQ_SNACxFAM_LISTS,ICQ_SNACxLISTS_REQUESTxROSTER)
+{
+	printf("%x\n",nrecords);
+	m_nSize += 4 + 2;
+	buffer->PackUnsignedLongBE(saved_time);
+	buffer->PackUnsignedShortBE(nrecords);
+}
+
 CPU_GenericFamily::CPU_GenericFamily(unsigned short Family, unsigned short SubType)
Index: src/user.cpp
===================================================================
RCS file: /cvsroot/licq/licq/src/user.cpp,v
retrieving revision 1.36
diff -u -1 -b -p -r1.36 user.cpp
--- src/user.cpp	19 Mar 2002 06:54:24 -0000	1.36
+++ src/user.cpp	25 Apr 2002 00:09:07 -0000
@@ -906,2 +906,3 @@ void ICQUser::LoadLicqInfo()
   SetHistoryFile(szTemp);
+  m_fConf.ReadNum("SID",m_nSID,0);
 
@@ -1112,2 +1113,3 @@ void ICQUser::Init(unsigned long _nUin)
   m_bConnectionInProgress = false;
+  m_nSID = 0;
 
@@ -1876,2 +1878,3 @@ void ICQUser::SaveLicqInfo()
    m_fConf.WriteStr("UserEncoding", m_szEncoding);
+   m_fConf.WriteNum("SID",m_nSID);
 
@@ -2149,2 +2152,4 @@ ICQOwner::ICQOwner()
   m_fConf.ReadStr("AutoResponse", szTemp, "");
+  m_fConf.ReadNum("SSTime", (unsigned long)m_nSStime, 0L);
+  m_fConf.ReadNum("SSCount",m_nSScount, 0);
   SetAutoResponse(szTemp);
@@ -2225,2 +2230,4 @@ void ICQOwner::SaveLicqInfo()
   m_fConf.WriteNum("RCG", RandomChatGroup());
+  m_fConf.WriteNum("SSTime", (unsigned long)m_nSStime);
+  m_fConf.WriteNum("SSCount",m_nSScount);
 
/*
 * LISTS snac family  chain processing. 
 * (server side contact list managment)
 *
 * Originaly by Juan F. Codagnone <[EMAIL PROTECTED]>
 * 
 * Information taken from:
 * 	o from Massimo Melina protocol notes (www.rejetto.com/icq)
 *	o Stricq (www.stricq.com/icqv8/Command_view.cfm)
 */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

/*
 *#include <stdio.h>
 *#include <string.h>
 *#include <sys/types.h>
 *#include <unistd.h>
 *#include <errno.h>
 */
#include "time-fix.h"

#include "licq_icqd.h"
#include "licq_translate.h"
#include "licq_packets.h"
#include "licq_socket.h"
#include "licq_user.h"
#include "licq_events.h"
#include "licq_log.h"
#include "support.h"
#include "licq_message.h"

//--------ProcessListsFam------------------------------------------------------
enum roster_type
{	RRHT_CNORMA = 0x0000,	// a normal contact list entry
	RRHT_LGROUP = 0x0001,	// larger grouping header
	RRHT_CINVIS = 0x0003,	// a contact on the Invisible List
	RRHT_VISIBS = 0x0004,	// visibility setting.  TLV(00CA)
	RRHT_CIGNOR = 0x000E,	// a contact on the Ignore List
	RRHT_ICQTIC = 0x0009,	// i don't know what the hell this represent
	RRHT_IMPORT = 0x0013,	// TLV contains the time(NULL) 'Import Time'
}; 

const unsigned short MAX_TLV = 4;

struct roster
{	
	// names the group, either a contact UIN or a larger grouping title
	// based upon the TAG value.
	char *name;

	// tag or marker associating different groups together  into a larger
	//group such as the Ignore List or 'General' contact list group, etc.
	unsigned short tag;

	// random number generated when the user is added to the contact list,
	// or when the user is ignored
	unsigned short id;	

	enum roster_type type; 

	// number of TLVs 
	unsigned short nparam;
	// array of TLVs
	SOscarTLV param[MAX_TLV];
};

/*	extract a roster struct from the `packet' 
 */
static struct roster *
roster_body_extract( CBuffer &packet, struct roster *r)
{	unsigned short i,j,k=0,bytelen;
	assert( r );
	
	r->name = packet.UnpackStringBE();
	r->tag  = packet.UnpackUnsignedShortBE();
	r->id   = packet.UnpackUnsignedShortBE();
	r->type = (enum roster_type)packet.UnpackUnsignedShortBE();
	bytelen = packet.UnpackUnsignedShortBE();

	if( bytelen )
	{	// several TLVs. usually 1
		for( k=i=0 ; i<bytelen && k<MAX_TLV ; i+=4,k++ )
		{	r->param[k].nType = packet.UnpackUnsignedShortBE();
			r->param[k].nLen  = packet.UnpackUnsignedShortBE();

			// nLen + 1 so in the strings we can add the NIL
			r->param[k].pData=new unsigned char[r->param[k].nLen+1];
			for( j = 0; i<r->param[k].nLen && i<bytelen;j++,i++ )
				r->param[k].pData[j] = 
					(unsigned char)packet.UnpackChar();
			r->param[k].pData[j] = '\0';
		}

		/* opps we ran out of space. should never happend (MAX_TLV) 
		 * should be big enougth...we eat the rests of the bytes
		 */
		if( k == MAX_TLV )
		{	for( ;i<bytelen;i++ ) 
				packet.UnpackChar();
			cerr << "Opps. increment MAX_TLV \n";
		}
	}
	r->nparam = k;

	return r;
}

/* Free's roster_body_extract() data
 */
static void
roster_body_free( struct roster *r )
{	unsigned short i;
	assert(r);

	for( i=0 ; i<r->nparam ; i++ )
		delete r->param[i].pData;
}

static bool
roster_body_contact( const struct roster *r )
{	char *t;

	if(  r->nparam == 0 || r->param[0].nType != 0x0131)
	{	cerr << "RRHT_NORMAL invalid\n";
		return false;
	}
	
	switch( r->type )
	{	case RRHT_CINVIS: t = " (Invisible)";	break;
		case RRHT_CIGNOR: t = " (Ignore)";	break;
		case RRHT_CNORMA: t = " (Normal)";	break;
		default:	  t = " (!!!!!)"; 	
	}
	
	cerr << " UIN: "   << r->name
	     << " NAME: '" << r->param[0].pData << "'"
	     << " ID: "    << r->id 
	     << " GROUPID "<< r->tag
	     <<   t  
	     << ( (r->nparam>1 && r->param[1].nType==0x0066) ?
	     		"(Waiting auth)": " ")
	     <<"\n"; 

	return true;
}

static bool
roster_body_lgroup( const struct roster *r )
{	unsigned short *id,i,gid;
	const char *gname ;

	// if there is a TLV should be C8
	if( r->nparam!= 0 && r->param[0].nType != 0x00C8 ) 
	{	cerr << " Invalid TLV in lgroup\n";
		return false;
	}

	if( r->name[0] == '\0' )
	{	// no name means that we have a TLV(C8) with groups ids
		if(  r->nparam != 0 )
		{	for( i = 0; i<r->param[0].nLen; i+=2 )
			{	id = (unsigned short *)(r->param[0].pData + i);
				cerr << "Group ID: "<< get_be_short((char *)id)
				     <<"\n";
			}
		}
	}
	else
	{	// normal group: Eg: name=="Family" TLV(C8)=00 02
		if( r->name[0] ==  '\0' )
			gname = "Unamed";
		else 
			gname = r->name;
		gid = *( (unsigned short *)(r->param[0].pData) );	

		cerr << "Group:"
		     << " GID: "<< r->tag
		     << " G#: " << gid 
		     << " Name: " << gname 
		     << "\n";
	}

	return true;
}

static bool
roster_body_vsettings(  const struct roster *r )
{	unsigned short i;

	for( i = 0; i<r->param[0].nLen ; i++ )
	{	cerr << "Visibily setting: ";
		switch( r->param[0].pData[i] )
		{	case 0x0001:
				cerr <<"Allow all users to see us\n";
				break;
			case 0x0002:
				cerr <<"Block all users from seeing us\n";
				break;
			case 0x0003:
				cerr <<"Allow only users in the permit list"
					" to see us\n";
				break;
			case 0x0004:
				cerr <<"Block only users in the "
					"invisible list from seeing us\n";
				break;
			case 0x0005:
				cerr <<"Allow only users in the buddy"
					" list to see you\n";
				break;
			default:
				cerr << "Unknow\n";
		}
	}
	return true;
}

static bool
roster_body_importtime( const struct roster *r )
{	
	if( r->param[0].nType != 0x00d4 )
	{	cerr << "bad TLV (should be d4)\n";
		return false;
	}
	if( r->name[0] )
		cerr << r->name[0]<<" "<< *((unsigned long *)r->param[0].pData);
	return true;
}

static bool
roster_body_icqtic( const struct roster *r)
{
	cerr << "ICQTIC (do you know the meaning?)\n"
	     << "TAG = "<< r->tag << "\n"
	     << "ID  = "<< r->id  << "\n"
	     << "NP  = "<< r->nparam << "\n"
	     << "TLV = "<< r->param[0].pData
	     << "\n";
	return true;
}

static bool
roster_body_default( const struct roster *r )
{	unsigned short i;

	cerr << "Unknown roster\n"
	     << " name " << r->name << "\n"
	     << "  tag " << r->tag << "\n"
	     << "  id  " << r->id << "\n"
	     << "type  " << r->type << "\n"
	     << " len  " << r->nparam << "\n";

	for( i=0; i<r->nparam ; i++ )
	{	cerr << "   TLV(" <<  r->param[i].nType <<") "
		     << "Len: "<< r->param[i].nLen 
		     << "\n";
	}
	return true;
}

void CICQDaemon::ProcessListsFam( CBuffer &packet, unsigned short nSubtype)
{
    CSrvPacketTcp *p;
    unsigned short flags;
    unsigned long  ref;

    
    flags = packet.UnpackUnsignedShortBE();
    ref   = packet.UnpackUnsignedLong();
    
    switch( nSubtype )
    {
	case ICQ_SNACxLISTS_RIGHTSxGRANTED:
	{	gLog.Info("%sServer granted us the Server Contact List\n",
			L_SRVxSTR);
		gLog.Info("%sRequesting saved contact List\n",L_SRVxSTR);

		// TODO: save the time_t of the last saved and ask for
		// TODO: new contacs insted of only requesting all.
		CSrvPacketTcp* p = new  CPU_GenericFamily(ICQ_SNACxFAM_LISTS,
					ICQ_SNACxLISTS_REQUESTxROSTER2);
		SendEvent_Server(p);
		break;
	}
	case ICQ_SNACxLISTS_ROSTERxREPLY:
	{	struct roster r;
		unsigned short count,i;
		unsigned long stime;
		
		gLog.Info("%sServer sent us the contact list\n",L_SRVxSTR);

		packet.UnpackChar();	// unknow
		count = packet.UnpackUnsignedShortBE();

		for( i=0; i<count ; i++)
		{ 	cerr << "--------" << i << "-------\n";
			roster_body_extract(packet,&r);

			// process
			switch (r.type)
			{	case RRHT_CIGNOR:
				case RRHT_CINVIS:
				case RRHT_CNORMA:
					roster_body_contact(&r);
					break;
				case RRHT_LGROUP:
					roster_body_lgroup(&r);
					break;
				case RRHT_VISIBS:
					roster_body_vsettings(&r);
					break;
				case RRHT_IMPORT:
					roster_body_importtime(&r);
					break;
				case RRHT_ICQTIC:
					roster_body_icqtic(&r);
					break;
				default:
					roster_body_default(&r);
					break;
				
			}
			roster_body_free(&r);
		}
		stime = packet.UnpackUnsignedLongBE();
		cerr << "time_t = " << ctime((time_t *)&stime);

		ICQOwner *o = gUserManager.FetchOwner(LOCK_W);
		o->SetSSCheck( stime );
		o->SetSSCount( count );
		gUserManager.DropOwner();

		// Send ack
		p = new CPU_GenericFamily(ICQ_SNACxFAM_LISTS,
					 ICQ_SNACxLISTS_ROSTERxACK);
		SendEvent_Server(p);
		break;
	}
	case ICQ_SNACxLISTS_REMOVEXACK:
		// not yet
	default:
	{	char *buf;

		gLog.Unknown("%sUnknow List UIN Family Subtype: %04hx\n%s\n",
				L_UNKNOWNxSTR,nSubtype, packet.print(buf));
		delete [] buf;
	}
    }
    return;
}

Reply via email to