changeset 1309:0a766047b4fd

[gaim-migrate @ 1319] Yay, new icqlib committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Tue, 19 Dec 2000 10:08:29 +0000
parents 4741b5a75b9f
children 035945fca2d5
files ChangeLog plugins/icq/.cvsignore plugins/icq/CHANGES_SINCE_1.0 plugins/icq/ChangeLog plugins/icq/Makefile.am plugins/icq/VERSION plugins/icq/chatsession.c plugins/icq/contacts.c plugins/icq/cyrillic.c plugins/icq/eventhandle.c plugins/icq/eventhandle.h plugins/icq/filesession.c plugins/icq/gaim_icq.c plugins/icq/icq.h plugins/icq/icqbyteorder.c plugins/icq/icqbyteorder.h plugins/icq/icqevent.c plugins/icq/icqevent.h plugins/icq/icqlib.c plugins/icq/icqlib.h plugins/icq/icqpacket.c plugins/icq/list.c plugins/icq/proxy.c plugins/icq/queue.c plugins/icq/stdpackets.c plugins/icq/stdpackets.h plugins/icq/tcp.c plugins/icq/tcp.h plugins/icq/tcpchathandle.c plugins/icq/tcpfilehandle.c plugins/icq/tcphandle.c plugins/icq/tcplink.c plugins/icq/udp.c plugins/icq/udphandle.c plugins/icq/util.c
diffstat 35 files changed, 1337 insertions(+), 196 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Tue Dec 19 08:37:12 2000 +0000
+++ b/ChangeLog	Tue Dec 19 10:08:29 2000 +0000
@@ -1,5 +1,9 @@
 GAIM: The Pimpin' Penguin IM Clone thats good for the soul! 
 
+version 0.11.0:
+	* ICQ upgraded to use icqlib 1.1.0
+	* An enormous amount of bug fixes
+
 version 0.11.0-pre3 (12/15/2000):
 	* Away messages arranged alphabetically (Thanks Justin)
 	* More GUI adjustments
--- a/plugins/icq/.cvsignore	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/.cvsignore	Tue Dec 19 10:08:29 2000 +0000
@@ -5,8 +5,10 @@
 chatsession.lo
 contacts.lo
 cyrillic.lo
+eventhandle.lo
 filesession.lo
 icqbyteorder.lo
+icqevent.lo
 icqlib.lo
 icqpacket.lo
 list.lo
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/CHANGES_SINCE_1.0	Tue Dec 19 10:08:29 2000 +0000
@@ -0,0 +1,23 @@
+
+This file is intendended to be a list of source incompatable changes have 
+been made since icqlib-1.0.0.
+
+2000-12-19: ICQLINKs have been reworked.  Members that provide no useful 
+information to the library client have been moved to a private structure 
+attached to the public ICQLINK, ICQLINK_private.  See icqlib.h.  ICQLINK 
+memory management now must be performed by the library (which is probably 
+how it should have always been), with icq_ICQLINKNew and 
+icq_ICQLINKDelete.
+
+2000-12-19: Your application is no longer responsible for allocating and
+freeing the ICQLINK structure, rather, it is returned as the result of a
+icq_ICQLINKNew call.  icq_ICQLINKDelete will free an ICQLINK structure.
+
+2000-12-19: icq_Init and icq_Done have been removed.  Use icq_ICQLINKNew
+and icq_ICQLINKDelete instead.  In addition, icq_ICQLINKNew has gained an
+additional parameter: a flag to turn TCP on or off.
+
+
+
+
+
--- a/plugins/icq/ChangeLog	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/ChangeLog	Tue Dec 19 10:08:29 2000 +0000
@@ -1,3 +1,52 @@
+
+2000-12-19  Bill Soudan  <wes0472@rit.edu>
+
+	* icqlib/chatsession.c, icqlib/contacts.c, icqlib/eventhandle.c,
+	icqlib/filesession.c, icqlib/icq.h.in, icqlib/icqlib.c,
+	icqlib/icqlib.h, icqlib/queue.c, icqlib/stdpackets.c,
+	icqlib/tcp.c, icqlib/tcplink.c icqlib/udp.c: moved some ICQLINK
+	members to ICQLINK_private structures, added icq_ICQLINKNew and
+	icq_ICQLINKDelete functions which replace icq_Init and icq_Done
+
+	* CHANGES_SINCE_1.0: lists source incompatable changes since
+	1.0 release.
+
+	* VERSION: bumped version number to 1.1
+
+2000-12-06  Denis V. Dmitrienko  <denis@null.net>
+
+	* icqlib/queue.c, icqlib/stdpackets.h, icqlib/tcp.h, icqlib/tcphandle.c:
+	Handling for mass TCP messages has been added based on patch by
+	Konstantin Klyagin <konst@konst.org.ua>
+
+2000-12-03  Bill Soudan  <soudan@kde.org>
+
+	* icqlib/queue.c: fixed compilation with gcc-2.96
+
+	* icqlib/tcplink.c: fixed bug #105068
+
+2000-11-02  Denis V. Dmitrienko  <denis@null.net>
+
+	* icqlib/icq.h.in, icqlib/icqlib.c, icqlib/udp.c:
+	Ability to disable TCP protocol has been added.
+
+	* icqlib/udphandle.c: Do not ack unhandled protocol version.
+
+2000-08-13  Denis V. Dmitrienko  <denis@null.net>
+
+	* icqlib/tcphandle.c:
+	Cyrillic recoding on received URL description added.
+
+	* icqlib/icq.h.in, icqlib/util.c: icq_Genders[] array have been added.
+
+2000-08-13  Denis V. Dmitrienko  <denis@null.net>
+
+	* icqlib/udp.c: Patch #101057 have been applied.
+
+2000-07-31  Denis V. Dmitrienko  <denis@null.net>
+
+	* .cvsignore, Makefile.am: Little modifications before releasing.
+
 2000-07-30  Denis V. Dmitrienko  <denis@null.net>
 
 	* ChangeLog, icqlib-0.2.0.lsm, icqlib-1.0.0.lsm, README, TODO,
--- a/plugins/icq/Makefile.am	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/Makefile.am	Tue Dec 19 10:08:29 2000 +0000
@@ -16,11 +16,15 @@
 			contacts.c \
 			contacts.h \
 			cyrillic.c \
+			eventhandle.c \
+			eventhandle.h \
 			filesession.c \
 			filesession.h \
 			icq.h \
 			icqbyteorder.c \
 			icqbyteorder.h \
+			icqevent.c \
+			icqevent.h \
 			icqlib.c \
 			icqlib.h \
 			icqpacket.c \
--- a/plugins/icq/VERSION	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/VERSION	Tue Dec 19 10:08:29 2000 +0000
@@ -1,1 +1,1 @@
-1.0.0
+1.1.0
--- a/plugins/icq/chatsession.c	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/chatsession.c	Tue Dec 19 10:08:29 2000 +0000
@@ -1,6 +1,7 @@
 
 #include <stdlib.h>
 
+#include "icqlib.h"
 #include "chatsession.h"
 #include "list.h"
 
@@ -14,7 +15,7 @@
     p->status=0;
     p->id=0L;
     p->icqlink=icqlink;
-    list_insert(icqlink->icq_ChatSessions, 0, p);
+    list_insert(icqlink->d->icq_ChatSessions, 0, p);
   }
 	
   return p;
@@ -27,7 +28,7 @@
 
 void icq_ChatSessionClose(icq_ChatSession *p)
 {
-  list_remove(p->icqlink->icq_ChatSessions, p);
+  list_remove(p->icqlink->d->icq_ChatSessions, p);
   icq_ChatSessionDelete(p);
 }
 
@@ -39,7 +40,7 @@
 
 icq_ChatSession *icq_FindChatSession(ICQLINK *icqlink, DWORD uin)
 {
-  return list_traverse(icqlink->icq_ChatSessions,
+  return list_traverse(icqlink->d->icq_ChatSessions,
     _icq_FindChatSession, uin);
 }
 
--- a/plugins/icq/contacts.c	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/contacts.c	Tue Dec 19 10:08:29 2000 +0000
@@ -1,9 +1,12 @@
 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
-$Id: contacts.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Id: contacts.c 1319 2000-12-19 10:08:29Z warmenhoven $
 $Log$
-Revision 1.1  2000/11/28 02:22:42  warmenhoven
-icq. whoop de doo
+Revision 1.2  2000/12/19 10:08:29  warmenhoven
+Yay, new icqlib
+
+Revision 1.5  2000/12/19 06:00:07  bills
+moved members from ICQLINK to ICQLINK_private struct
 
 Revision 1.4  2000/06/17 16:38:45  denis
 New parameter was added in icq_ContactSetVis() for setting/resetting
@@ -25,9 +28,10 @@
 #include <stdlib.h>
 #include <stdarg.h>
 
+#include "icq.h"
+#include "icqlib.h"
 #include "icqtypes.h"
 #include "util.h"
-#include "icq.h"
 #include "list.h"
 #include "contacts.h"
 
@@ -53,7 +57,7 @@
   p->uin = cuin;
   p->vis_list = FALSE;
 
-  list_enqueue(link->icq_ContactList, p);
+  list_enqueue(link->d->icq_ContactList, p);
 }
 
 void icq_ContactRemove(ICQLINK *link, DWORD cuin)
@@ -62,15 +66,15 @@
 
   if (pcontact)
   {
-    list_remove(link->icq_ContactList, pcontact);
+    list_remove(link->d->icq_ContactList, pcontact);
     icq_ContactDelete(pcontact);
   }
 }
 
 void icq_ContactClear(ICQLINK *link)
 {
-  list_delete(link->icq_ContactList, icq_ContactDelete);
-  link->icq_ContactList=list_new();
+  list_delete(link->d->icq_ContactList, icq_ContactDelete);
+  link->d->icq_ContactList=list_new();
 }
 
 int _icq_ContactFind(void *p, va_list data)
@@ -82,7 +86,7 @@
 
 icq_ContactItem *icq_ContactFind(ICQLINK *link, DWORD cuin)
 {
-  return list_traverse(link->icq_ContactList, _icq_ContactFind, cuin);
+  return list_traverse(link->d->icq_ContactList, _icq_ContactFind, cuin);
 }
 
 void icq_ContactSetVis(ICQLINK *link, DWORD cuin, BYTE vu)
@@ -94,12 +98,12 @@
 
 icq_ContactItem *icq_ContactGetFirst(ICQLINK *link)
 {
-  return list_first(link->icq_ContactList);
+  return list_first(link->d->icq_ContactList);
 }
 
 icq_ContactItem *icq_ContactGetNext(icq_ContactItem *pcontact)
 {
-  list_node *p=list_find(pcontact->icqlink->icq_ContactList, pcontact);
+  list_node *p=list_find(pcontact->icqlink->d->icq_ContactList, pcontact);
 
   if (p && p->next)
     return p->next->item;
--- a/plugins/icq/cyrillic.c	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/cyrillic.c	Tue Dec 19 10:08:29 2000 +0000
@@ -1,9 +1,9 @@
 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
-$Id: cyrillic.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Id: cyrillic.c 1319 2000-12-19 10:08:29Z warmenhoven $
 $Log$
-Revision 1.1  2000/11/28 02:22:42  warmenhoven
-icq. whoop de doo
+Revision 1.2  2000/12/19 10:08:29  warmenhoven
+Yay, new icqlib
 
 Revision 1.7  2000/05/21 17:41:14  denis
 Applied patch for russian letters IO and io by
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/eventhandle.c	Tue Dec 19 10:08:29 2000 +0000
@@ -0,0 +1,243 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+/* 
+ * $Id: eventhandle.c 1319 2000-12-19 10:08:29Z warmenhoven $
+ *
+ * $Log$
+ * Revision 1.1  2000/12/19 10:08:29  warmenhoven
+ * Yay, new icqlib
+ *
+ * Revision 1.3  2000/12/19 06:00:07  bills
+ * moved members from ICQLINK to ICQLINK_private struct
+ *
+ * Revision 1.1  2000/06/15 18:50:03  bills
+ * committed for safekeeping - this code will soon replace tcphandle.c 
+ *
+*/
+
+#include <time.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#include "icqevent.h"
+#include "icqpacket.h"
+#include "tcplink.h"
+#include "chatsession.h"
+#include "filesession.h"
+
+#include "eventhandle.h"
+
+void icq_TCPProcessPacket2(icq_Packet *p, icq_TCPLink *plink)
+{
+  icq_MessageEvent *pevent=(icq_MessageEvent *)icq_ParsePacket(p);
+  icq_Event *pbase=(icq_Event *)pevent;
+
+  ICQLINK *icqlink=plink->icqlink;
+
+  if (pbase->uin != plink->remote_uin)
+  {
+    /* TODO: spoofed packet! */
+  }
+
+  pbase->handleEvent(pbase, icqlink);
+
+  /* notify library client than the ack was received from remote client */
+  if (pbase->subtype==ICQ_EVENT_ACK)
+  {
+    icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, "received ack %d\n", p->id);
+    if(icqlink->icq_RequestNotify)
+    {
+      (*icqlink->icq_RequestNotify)(icqlink, pbase->id,
+        ICQ_NOTIFY_ACK, pevent->status, (void *)pevent->message);
+      (*icqlink->icq_RequestNotify)(icqlink, pbase->id,
+        ICQ_NOTIFY_SUCCESS, 0, 0);
+    }
+  }    
+}
+
+void icq_HandleMessageEvent(icq_Event *pbase, ICQLINK *icqlink)
+{
+  icq_MessageEvent *pevent=(icq_MessageEvent *)pbase;
+  struct tm *ptime=localtime(&(pbase->time));
+
+  if (pbase->subtype==ICQ_EVENT_MESSAGE && icqlink->icq_RecvMessage)
+  {
+    (*icqlink->icq_RecvMessage)(icqlink, pbase->uin, ptime->tm_hour,
+      ptime->tm_min, ptime->tm_mday, ptime->tm_mon+1,
+      ptime->tm_year+1900, pevent->message);
+    /* TODO: send ack */
+  }
+
+}
+
+void icq_HandleURLEvent(icq_Event *pbase, ICQLINK *icqlink) 
+{
+  icq_URLEvent *pevent=(icq_URLEvent *)pbase;
+  struct tm *ptime=localtime(&(pbase->time));
+
+  if (pbase->subtype==ICQ_EVENT_MESSAGE && icqlink->icq_RecvURL)
+  {
+    (*icqlink->icq_RecvURL)(icqlink, pbase->uin, ptime->tm_hour,
+      ptime->tm_min, ptime->tm_mday, ptime->tm_mon+1,
+      ptime->tm_year+1900, pevent->url, pevent->message);
+    /* TODO: send ack */
+  }
+}
+
+void icq_HandleChatRequestEvent(icq_Event *pbase, ICQLINK *icqlink)
+{
+  icq_ChatRequestEvent *pevent=(icq_ChatRequestEvent *)pbase;
+  icq_MessageEvent *pmsgevent=(icq_MessageEvent *)pmsgevent;
+
+  struct tm *ptime=localtime(&(pbase->time));
+
+  switch(pbase->subtype)
+  {
+    case ICQ_EVENT_MESSAGE:
+      if (icqlink->icq_RecvChatReq)
+        (*icqlink->icq_RecvChatReq)(icqlink, pbase->uin,
+          ptime->tm_hour, ptime->tm_min, ptime->tm_mday, ptime->tm_mon+1,
+          ptime->tm_year+1900, pmsgevent->message, pbase->id);
+      /* don't send an ack to the remote client!  library client is
+       * responsible for sending the ack once the user accepts
+       * or denies the request */
+      break;
+    case ICQ_EVENT_ACK:
+      icq_HandleChatRequestAck(pbase, icqlink);
+      break;
+    case ICQ_EVENT_CANCEL:
+      /* TODO */
+      break;
+    default:
+      /* TODO */
+      break;
+  }
+}
+
+void icq_HandleChatRequestAck(icq_Event *pbase, ICQLINK *icqlink)
+{
+  icq_ChatRequestEvent *pevent=(icq_ChatRequestEvent *)pbase;
+  icq_TCPLink *pchatlink;
+  icq_ChatSession *pchat;
+  icq_Packet *p2;
+
+  /* once a chat request acknowledgement has been received, the remote
+   * client opens up a listening port for us.  we need to connect to
+   * this port and all chat session communication takes place over
+   * this new tcp link */
+  pchatlink=icq_TCPLinkNew(icqlink);
+  pchatlink->type=TCP_LINK_CHAT;
+  pchatlink->id=pbase->id;
+
+  /* create a new chat session to manage the communication, and link
+   * it to the tcp link */
+  pchat=icq_ChatSessionNew(icqlink);
+  pchat->id=pbase->id;
+  pchat->remote_uin=pbase->uin;
+  pchatlink->session=pchat;
+
+  icq_ChatSessionSetStatus(pchat, CHAT_STATUS_CONNECTING);
+
+  /* initiate the connection to the remote client's chat session 
+   * port, which was specified in the ack event they sent */
+  icq_TCPLinkConnect(pchatlink, pbase->uin, pevent->port);
+
+  /* send off chat init event */
+  p2=icq_TCPCreateChatInfoPacket(pchatlink, icqlink->icq_Nick, 0x00ffffff,
+    0x00000000);
+  icq_TCPLinkSend(pchatlink, p2);  
+}
+
+
+void icq_HandleFileRequestEvent(icq_Event *pbase, ICQLINK *icqlink)
+{
+  icq_FileRequestEvent *pevent=(icq_FileRequestEvent *)pbase;
+  icq_MessageEvent *pmsgevent=(icq_MessageEvent *)pmsgevent;
+  struct tm *ptime=localtime(&(pbase->time));
+
+  switch(pbase->subtype)
+  {
+    case ICQ_EVENT_MESSAGE:
+      if (icqlink->icq_RecvFileReq)
+        (*icqlink->icq_RecvFileReq)(icqlink, pbase->uin,
+          ptime->tm_hour, ptime->tm_min, ptime->tm_mday, ptime->tm_mon+1,
+          ptime->tm_year+1900, pmsgevent->message, pevent->filename,
+          pevent->filesize, pbase->id);
+      /* don't send an ack to the remote client!  library client is
+       * responsible for sending the ack once the user accepts
+       * or denies the request */
+      break;
+    case ICQ_EVENT_ACK:
+      icq_HandleFileRequestAck(pbase, icqlink);
+      break;
+    case ICQ_EVENT_CANCEL:
+      break;
+    default:
+      /* TODO */
+      break;
+  }
+}
+
+void icq_HandleFileRequestAck(icq_Event *pbase, ICQLINK *icqlink)
+{
+  icq_FileRequestEvent *pevent=(icq_FileRequestEvent *)pbase;
+  icq_TCPLink *pfilelink;
+  icq_FileSession *pfile;
+  icq_Packet *p2;
+
+  /* once a file request acknowledgement has been received, the remote
+   * client opens up a listening port for us.  we need to connect to
+   * this port and all file transfer communication takes place over
+   * this new tcp link */
+  pfilelink=icq_TCPLinkNew(icqlink);
+  pfilelink->type=TCP_LINK_FILE;
+
+  /* a file session was created when the request was initially sent,
+   * but it wasn't attached to a tcp link because one did not exist. 
+   * find the file sesion now and link it to the new tcp link */
+  pfile=icq_FindFileSession(icqlink, pbase->uin, 
+    pbase->id); /* TODO: make sure find session succeeded */
+  pfile->tcplink=pfilelink;
+  pfilelink->id=pfile->id;
+  pfilelink->session=pfile;
+
+  /* notify the library client of the created file session */
+  if (icqlink->icq_RequestNotify)
+    (*icqlink->icq_RequestNotify)(icqlink, pfile->id,
+      ICQ_NOTIFY_FILESESSION, sizeof(icq_FileSession), pfile);
+  icq_FileSessionSetStatus(pfile, FILE_STATUS_CONNECTING);
+
+  /* initiate the connection to the remote client's file session 
+   * port, which was specified in the ack event they sent */
+  icq_TCPLinkConnect(pfilelink, pbase->uin, pevent->port);
+
+  /* send off the file transfer init event */
+  /* TODO: convert file packets to events */
+  p2=icq_TCPCreateFile00Packet( pfile->total_files,
+    pfile->total_bytes, pfile->current_speed, icqlink->icq_Nick);
+  icq_TCPLinkSend(pfilelink, p2); 
+}
+
+
+/*
+icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "unknown message type %d!\n", type);
+icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "unknown packet command %d!\n",
+ command); 
+
+ TODO: conversion
+    strncpy(data,message,512) ;
+    icq_RusConv("wk",data) ;
+
+
+ TODO: ack code
+
+    if(plink)
+    {
+      pack=icq_TCPCreateMessageAck(plink,0);
+      icq_PacketAppend32(pack, id);
+      icq_PacketSend(pack, plink->socket);
+      icq_PacketDelete(pack);
+    }
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/eventhandle.h	Tue Dec 19 10:08:29 2000 +0000
@@ -0,0 +1,30 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+/*
+ * $Id: eventhandle.h 1319 2000-12-19 10:08:29Z warmenhoven $
+ *
+ * $Log$
+ * Revision 1.1  2000/12/19 10:08:29  warmenhoven
+ * Yay, new icqlib
+ *
+ * Revision 1.1  2000/06/15 18:50:03  bills
+ * committed for safekeeping - this code will soon replace tcphandle.c
+ *
+*/
+
+#ifndef _EVENTHANDLE_H
+#define _EVENTHANDLE_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+void icq_HandleMessageEvent(icq_Event *pevent, ICQLINK *icqlink);
+void icq_HandleURLEvent(icq_Event *pevent, ICQLINK *icqlink);
+void icq_HandleChatRequestEvent(icq_Event *base, ICQLINK *icqlink);
+void icq_HandleFileRequestEvent(icq_Event *base, ICQLINK *icqlink);
+
+void icq_HandleChatRequestAck(icq_Event *pevent, ICQLINK *icqlink);
+void icq_HandleFileRequestAck(icq_Event *pevent, ICQLINK *icqlink);
+
+#endif /* _EVENTHANDLE_H */
--- a/plugins/icq/filesession.c	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/filesession.c	Tue Dec 19 10:08:29 2000 +0000
@@ -12,6 +12,7 @@
 #define write _write
 #endif
 
+#include "icqlib.h"
 #include "filesession.h"
 #include "list.h"
 #include "icqpacket.h"
@@ -36,7 +37,7 @@
     p->total_files=0;
     p->total_transferred_bytes=0;
     p->working_dir[0]=0;
-    list_insert(icqlink->icq_FileSessions, 0, p);
+    list_insert(icqlink->d->icq_FileSessions, 0, p);
   }
 	
   return p;
@@ -74,7 +75,7 @@
 icq_FileSession *icq_FindFileSession(ICQLINK *icqlink, DWORD uin,
   unsigned long id)
 {
-  return list_traverse(icqlink->icq_FileSessions, _icq_FindFileSession, 
+  return list_traverse(icqlink->d->icq_FileSessions, _icq_FindFileSession, 
     uin, id);
 }
 
@@ -218,7 +219,7 @@
 
   icq_FileSessionDelete(p);
 
-  list_remove(p->icqlink->icq_FileSessions, p);		
+  list_remove(p->icqlink->d->icq_FileSessions, p);		
 }   
 
 void icq_FileSessionSetWorkingDir(icq_FileSession *p, const char *dir)
--- a/plugins/icq/gaim_icq.c	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/gaim_icq.c	Tue Dec 19 10:08:29 2000 +0000
@@ -202,13 +202,12 @@
 static void icq_login(struct aim_user *user) {
 	struct gaim_connection *gc = new_gaim_conn(user);
 	struct icq_data *id = gc->proto_data = g_new0(struct icq_data, 1);
-	ICQLINK *link = id->link = g_new0(ICQLINK, 1);
+	ICQLINK *link = id->link = icq_ICQLINKNew(atol(user->username), user->password,
+			g_strdup("gaim user") /* hehe :) */, TRUE);
 	int icqSocket;
 
 	icq_LogLevel = ICQ_LOG_MESSAGE;
 
-	icq_Init(link, atol(user->username), user->password, "gaim user" /* hehe :) */);
-
 	link->icq_Logged = icq_online;
 	link->icq_Disconnected = icq_logged_off;
 	link->icq_RecvMessage = icq_msg_incoming;
@@ -250,8 +249,8 @@
 	gdk_input_remove(gc->inpa);
 	icq_Logout(id->link);
 	icq_Disconnect(id->link);
-	icq_Done(id->link);
-	g_free(id->link);
+	icq_ICQLINKDelete(id->link);
+	g_free(id);
 }
 
 static struct prpl *my_protocol = NULL;
--- a/plugins/icq/icq.h	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/icq.h	Tue Dec 19 10:08:29 2000 +0000
@@ -6,9 +6,9 @@
 #include <config.h>
 #endif
 
-#define ICQLIBVER   0x010000
+#define ICQLIBVER   0x010100
 #define ICQLIBMAJOR 1
-#define ICQLIBMINOR 0
+#define ICQLIBMINOR 1
 #define ICQLIBMICRO 0
 
 #include <time.h>
@@ -60,50 +60,96 @@
 extern "C" {
 #endif /* __cplusplus */
 
-typedef struct 
+typedef struct
 {
   const char *name;
   unsigned short code;
 } icq_ArrayType;
 
+struct icq_link_private;
+
+/**
+ * The ICQLINK structure represents a single connection to the ICQ  servers.
+ * It is returned as the result of an icq_ICQLINKNew function, and contains
+ * connection-specific parameters such as uin, sockets, current status, etc.
+ *
+ * This structure should be considered read-only.  Modifying it will cause
+ * undefined results.
+ */
 typedef struct icq_link
 {
-  /* General */
+
+  /* General parameters */
+  
+  /** User Identification Number.  This is your ICQ 'account' number. */
   unsigned long icq_Uin;
-  unsigned long icq_OurIP;          /* HOST byteorder */
-  unsigned short icq_OurPort;       /* HOST byteorder */
-  void *icq_ContactList;
+  
+  /** Our IP as understood by the ICQ server.  This will be set once an
+   * UDP_SRV_LOGIN_REPLY has been received from the ICQ servers, in host
+   * byteorder.  Note this may be different from the actual IP in cases
+   * such as firewalls, ip masquerading, etc. */
+  unsigned long icq_OurIP; 
+  
+  /** The UDP port used to connect to the ICQ server, in host byteorder.  */
+  unsigned short icq_OurPort;
+
+  /** Our current ICQ status: one of the STATUS_* defines.
+   * @see icq_StatusUpdate */
   unsigned long icq_Status;
+  
+  /** The password used to log into the ICQ server. */  
   char *icq_Password;
+  
+  /** The user's desired nickname. */
   char *icq_Nick;
 
   /* UDP stuff */
+
+  /** socket used to send and received UDP messages */
   int icq_UDPSok;
-  unsigned char icq_UDPServMess[8192]; /* 65536 seqs max, 1 bit per seq -> 65536/8 = 8192 */
-  unsigned short icq_UDPSeqNum1, icq_UDPSeqNum2;
-  unsigned long icq_UDPSession;
-  void *icq_UDPQueue;
+
+  /** Time, in seconds, that a sent UDP message can go without an ACK from the
+   * server before being retransmitted. */
   int icq_UDPExpireInterval;
 
   /* TCP stuff */
-  unsigned short icq_TCPSrvPort;    /* HOST byteorder */
-  int icq_TCPSequence;
-  void *icq_TCPLinks;
-  void *icq_ChatSessions;
-  void *icq_FileSessions;
-  int TCP_maxfd;
-  fd_set TCP_readfds;
-  fd_set TCP_writefds;
 
+  /** TCP listen port, in host byte order.  The TCP implementation will listen
+   * here for new connections from other clients.  This is transmitted as
+   * part of the ICQ login process. */
+  unsigned short icq_TCPSrvPort;
+  
+  /** Has TCP been enabled for this connection?
+   * @see icq_NewICQLINK */
+  unsigned char icq_UseTCP;
+  
   /* SOCKS5 Proxy stuff */
+  
+  /** Should all network traffic be redirected through a proxy? 
+   * @see icq_SetProxy */
   unsigned char icq_UseProxy;
+  
+  /** Hostname of the SOCKS5 proxy to use. */
   char *icq_ProxyHost;
-  unsigned long icq_ProxyIP;        /* HOST byteorder */
-  unsigned short icq_ProxyPort;     /* HOST byteorder */
+  
+  /** IP Address of the SOCKS5 proxy after DNS resolution, in host byteorder. */
+  unsigned long icq_ProxyIP;
+  
+  /** Port of the SOCKS5 proxy to use, in host byteorder. */
+  unsigned short icq_ProxyPort;
+  
+  /** What's this? :) */
   int  icq_ProxyAuth;
+  
+  /** Username used when logging into the proxy. */
   char *icq_ProxyName;
+  
+  /** Password used when logging into the proxy. */
   char *icq_ProxyPass;
+  
+  /** TCP socket used to communicate with the proxy. */
   int icq_ProxySok;
+    
   unsigned short icq_ProxyOurPort;  /* HOST byteorder */
   unsigned long icq_ProxyDestIP;    /* HOST byteorder */
   unsigned short icq_ProxyDestPort; /* HOST byteorder */
@@ -204,18 +250,27 @@
   void (*icq_MetaUserHomePageCategory)(struct icq_link *link,
        unsigned short seq2, unsigned char num, unsigned short hcat1,
        const char *htext1);
+       
+  /** Private data pointer. */
+  struct icq_link_private *d;
+  
 } ICQLINK;
 
 extern int icq_Russian;
 extern unsigned char icq_LogLevel;
 extern icq_ArrayType icq_Countries[];
+extern icq_ArrayType icq_Genders[];
 
 void icq_SetProxy(ICQLINK *link, const char *phost, unsigned short pport,
      int pauth, const char *pname, const char *ppass);
 void icq_UnsetProxy(ICQLINK *link);
 
+ICQLINK *icq_ICQLINKNew(unsigned long uin, const char *password,
+  const char *nick, unsigned char useTCP);
+void icq_ICQLINKDelete(ICQLINK *link);
+  
 void icq_Init(ICQLINK *link, unsigned long uin, const char *password,
-     const char *nick);
+     const char *nick, unsigned char useTCP);
 void icq_Done(ICQLINK *link);
 int icq_Connect(ICQLINK *link, const char *hostname, int port);
 void icq_Disconnect(ICQLINK *link);
--- a/plugins/icq/icqbyteorder.c	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/icqbyteorder.c	Tue Dec 19 10:08:29 2000 +0000
@@ -1,5 +1,5 @@
 /*
- * $Id: icqbyteorder.c 1162 2000-11-28 02:22:42Z warmenhoven $
+ * $Id: icqbyteorder.c 1319 2000-12-19 10:08:29Z warmenhoven $
  *
  * This header defines macros to handle ICQ protocol byte order conversion.
  *
--- a/plugins/icq/icqbyteorder.h	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/icqbyteorder.h	Tue Dec 19 10:08:29 2000 +0000
@@ -1,5 +1,5 @@
 /*
- * $Id: icqbyteorder.h 1162 2000-11-28 02:22:42Z warmenhoven $
+ * $Id: icqbyteorder.h 1319 2000-12-19 10:08:29Z warmenhoven $
  *
  * This header defines macros to handle ICQ protocol byte order conversion.
  *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/icqevent.c	Tue Dec 19 10:08:29 2000 +0000
@@ -0,0 +1,475 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+/*
+ * $Id: icqevent.c 1319 2000-12-19 10:08:29Z warmenhoven $
+ *
+ * $Log$
+ * Revision 1.1  2000/12/19 10:08:29  warmenhoven
+ * Yay, new icqlib
+ *
+ * Revision 1.2  2000/06/15 18:54:09  bills
+ * added time attribute and handleEvent function pointer to icq_Event,
+ * renamed icq_ChatEvent to icq_ChatRequestEvent, renamed icq_FileEvent to
+ * icq_FileRequestEvent, added icq_URLEvent and related methods
+ *
+ * Revision 1.1  2000/06/15 15:27:39  bills
+ * committed for safekeeping - this code will soon replace stdpackets.c and
+ * greatly simplify tcphandle.c, as well as reducing code duplication in many
+ * places.  it provides a much more flexible framework for managing events
+ * and parsing and creating packets
+ *
+*/
+
+#include <stdlib.h>
+
+#include "icqevent.h"
+#include "icqbyteorder.h"
+
+#ifdef EVENT_DEBUG
+#include <string.h>
+#include <stdio.h>
+#endif
+
+#define new_event(x, y)   y * x = ( y * )malloc(sizeof(y))
+
+/* generic Event - 'header' for each tcp packet */
+
+void icq_EventInit(icq_Event *p, int type, int subtype, unsigned long uin, 
+  int version)
+{
+  if (!p)
+    return;
+
+  p->uin=uin;
+  p->version=version;
+  p->type=type;
+  p->subtype=subtype;
+  p->direction=ICQ_EVENT_OUTGOING;
+}
+
+icq_Packet *icq_EventCreatePacket(icq_Event *pbase)
+{
+  icq_Packet *p=icq_PacketNew();
+
+  /* create header for tcp packet */
+  icq_PacketAppend32(p, pbase->uin);
+  icq_PacketAppend16(p, pbase->version);
+  icq_PacketAppend16(p, pbase->subtype);
+  icq_PacketAppend16(p, 0x0000);
+  icq_PacketAppend32(p, pbase->uin);
+  icq_PacketAppend32(p, pbase->type);
+
+  return p;
+}
+
+void icq_EventParsePacket(icq_Event *pevent, icq_Packet *p)
+{
+  /* parse header of tcp packet */
+  icq_PacketBegin(p);
+  (void)icq_PacketRead32(p);             /* uin */
+  pevent->version=icq_PacketRead16(p);   /* max supported tcp version */
+  pevent->subtype=icq_PacketRead16(p);   /* event subtype */
+  (void)icq_PacketRead16(p);             /* 0x0000 */
+  pevent->uin=icq_PacketRead32(p);       /* uin */
+  pevent->type=icq_PacketRead16(p);      /* event type */
+}
+
+/* Message Event - extends generic Event */
+
+icq_MessageEvent *icq_CreateMessageEvent(int subtype, unsigned long uin, 
+  const char *message) 
+{
+  new_event(p, icq_MessageEvent);
+  icq_Event *pbase=(icq_Event *)p;
+  icq_MessageEventInit(p, ICQ_TCP_MSG_MSG, subtype, uin,
+    ICQ_TCP_MSG_REAL, message);
+
+  pbase->createPacket=icq_MessageCreatePacket;
+
+#ifdef EVENT_DEBUG
+  pbase->eventName=icq_MessageEventName;
+  pbase->eventDump=icq_MessageEventDump;
+#endif
+
+  return p;
+}
+
+void icq_MessageEventInit(icq_MessageEvent *p, int type, int subtype, 
+  unsigned long uin, int msgtype, const char *message)
+{
+  icq_EventInit((icq_Event *)p, type, subtype, uin, ICQ_TCP_VER);
+  p->type=msgtype;
+  p->message=(char *)message;
+  p->status=0; /* FIXME */
+}
+
+icq_Packet *icq_MessageCreatePacket(icq_Event *pbase, icq_TCPLink *plink)
+{
+  icq_MessageEvent *pevent=(icq_MessageEvent *)pbase;
+
+  /* create header */
+  icq_Packet *p=icq_EventCreatePacket(pbase);
+
+  /* append data specific to message event */
+  icq_PacketAppendString(p, (char*)pevent->message);
+  icq_PacketAppend32(p, plink->socket_address.sin_addr.s_addr);
+  /* FIXME: should be RealIp */
+  icq_PacketAppend32(p, htonl(plink->icqlink->icq_OurIP));
+  icq_PacketAppend32(p, plink->socket_address.sin_port);
+  icq_PacketAppend8(p, 0x04);
+  icq_PacketAppend16(p, pevent->status);
+  icq_PacketAppend16(p, pevent->type);
+
+  return p;
+}
+
+void icq_MessageParsePacket(icq_Event *pbase, icq_Packet *p)
+{
+  icq_MessageEvent *pevent=(icq_MessageEvent *)pbase;
+
+  /* parse message event data from packet */
+  pevent->message=(char *)icq_PacketReadString(p);    /* message text */
+  (void)icq_PacketRead32(p);                  /* remote ip */
+  (void)icq_PacketRead32(p);                  /* remote real ip */
+  (void)icq_PacketRead32(p);                  /* remote message port */
+  (void)icq_PacketRead8(p);                   /* tcp flag */
+  pevent->status=icq_PacketRead16(p);         /* remote user status */
+  pevent->type=icq_PacketRead16(p);           /* message type */
+}
+
+#ifdef EVENT_DEBUG
+const char *icq_MessageEventName(icq_Event *p)
+{
+  if (p->type==ICQ_EVENT_MESSAGE)
+    return "message";
+  else if (p->type==ICQ_EVENT_ACK)
+    return "message ack";
+
+  return "message cancel";
+}
+
+const char *icq_MessageEventDump(icq_Event *p)
+{
+  static char buf[255];
+  icq_MessageEvent *pevent=(icq_MessageEvent *)p;
+
+  sprintf(buf, ", type=%x, message=\"%10s...\", status=%x",
+    pevent->type, pevent->message, pevent->status);
+
+  return buf;
+}
+#endif
+
+/* URL Event - extends message Event */
+
+icq_URLEvent *icq_CreateURLEvent(int subtype, unsigned long uin,
+  const char *message, const char *url)
+{
+  char *str=(char *)malloc(strlen(message)+strlen(url)+2);
+  icq_Event *pbase;
+  icq_URLEvent *p;
+
+  strcpy((char*)str, message);
+  *(str+strlen(message))=0xFE;
+  strcpy((char*)(str+strlen(message)+1), url);
+
+  /* TODO: make sure create message event copies message */
+  pbase=(icq_Event *)icq_CreateMessageEvent(subtype, uin, str);
+  p=(icq_URLEvent *)pbase;
+
+  free(str);
+
+  *(p->message+strlen(message))=0x00;
+  p->url=p->message+strlen(message)+1;
+
+  pbase->createPacket=icq_URLCreatePacket;
+
+#ifdef EVENT_DEBUG
+  pbase->eventName=icq_URLEventName;
+  pbase->eventDump=icq_URLEventDump;
+#endif
+
+  return p;
+
+}
+
+icq_Packet *icq_URLCreatePacket(icq_Event *pbase, icq_TCPLink *plink)
+{
+  icq_URLEvent *pevent=(icq_URLEvent *)pbase;
+  icq_Packet *p;
+
+  /* hack message string to include url */
+  *(pevent->message+strlen(pevent->message))=0xFE;
+
+  /* create packet */
+  p=icq_MessageCreatePacket(pbase, plink);
+
+  /* hack message string to seperate url */
+  *(pevent->message+strlen(pevent->message))=0x00;
+
+  return p;
+}
+
+void icq_URLParsePacket(icq_Event *pbase, icq_Packet *p)
+{
+  char *pfe;
+  icq_URLEvent *pevent=(icq_URLEvent *)pbase;
+
+  /* TODO: make sure messageparsepacket allocates message string
+   *       and add a delete event function */
+  icq_MessageParsePacket(pbase, p);
+
+  /* hack message string to seperate url */
+  pfe=strchr(pevent->message, '\xFE');
+  *pfe=0;
+  
+  /* set url */
+  pevent->url=pfe+1;
+
+}
+
+#ifdef EVENT_DEBUG
+const char *icq_URLEventName(icq_Event *p)
+{
+  if (p->type==ICQ_EVENT_MESSAGE)
+    return "url";
+  else if (p->type==ICQ_EVENT_ACK)
+    return "url ack";
+
+  return "url cancel";
+}
+
+const char *icq_URLEventDump(icq_Event *p)
+{
+  static char buf[255];
+  icq_MessageEvent *pevent=(icq_MessageEvent *)p;
+
+  sprintf(buf, ", type=%x, message=\"%10s...\", url=\"%10s...\" status=%x",
+    pevent->type, pevent->message, pevent->url, pevent->status);
+
+  return buf;
+}
+#endif
+
+
+/* Chat Request Event - extends Message Event */
+
+icq_ChatRequestEvent *icq_ChatRequestEventNew(int subtype,
+  unsigned long uin, const char *message, int port)
+{
+  new_event(p, icq_ChatRequestEvent);
+  icq_Event *pbase=(icq_Event *)p;
+  icq_MessageEventInit((icq_MessageEvent *)p, ICQ_TCP_MSG_CHAT, subtype,
+    uin, ICQ_TCP_MSG_REAL, message);
+  p->port=port;
+
+  pbase->createPacket=icq_ChatRequestCreatePacket;
+
+#ifdef EVENT_DEBUG
+  pbase->eventName=icq_ChatRequestEventName;
+  pbase->eventDump=icq_ChatRequestEventDump;
+#endif
+
+  return p;
+}
+
+icq_Packet *icq_ChatRequestCreatePacket(icq_Event *pbase, 
+  icq_TCPLink *plink)
+{
+  icq_ChatRequestEvent *pevent=(icq_ChatRequestEvent *)pbase;
+
+  /* create header and message data */
+  icq_Packet *p=icq_MessageCreatePacket(pbase, plink);
+
+  /* append data specific to chat event */
+  icq_PacketAppendString(p, 0);
+  icq_PacketAppend32(p, htonl(pevent->port));
+  icq_PacketAppend32(p, htoicql(pevent->port));  
+
+  return p;
+}
+
+void icq_ChatParsePacket(icq_Event *pbase, icq_Packet *p)
+{
+  icq_ChatRequestEvent *pevent=(icq_ChatRequestEvent *)pbase;
+  int port;
+
+  /* parse header and message event data */
+  icq_MessageParsePacket(pbase, p);
+
+  /* parse chat event data */
+  (void)icq_PacketReadString(p);      /* null string */
+  port=icq_PacketRead32(p);           /* chat listen port, network order */
+  (void)icq_PacketRead32(p);          /* chat listen port, intel order */
+
+  pevent->port=ntohl(port);
+}
+
+#ifdef EVENT_DEBUG
+const char *icq_ChatRequestEventName(icq_Event *p)
+{
+  if (p->type==ICQ_EVENT_MESSAGE)
+    return "chat request";
+  else if (p->type==ICQ_EVENT_ACK) {
+    icq_MessageEvent *pevent=(icq_MessageEvent *)p;
+    if (pevent->status==ICQ_TCP_STATUS_REFUSE)
+      return "chat request refuse";
+    else
+      return "chat request ack";
+  } else if (p->type==ICQ_EVENT_CANCEL) 
+    return "chat request cancel";
+
+  return "unknown chat request";
+}
+
+const char *icq_ChatRequestEventDump(icq_Event *p)
+{
+  static char buf[255];
+  static char buf2[255];
+  icq_ChatRequestEvent *pevent=(icq_ChatRequestEvent *)p;
+
+  strcpy(buf, icq_MessageEventDump(p));
+  sprintf(buf2, ", port=%d", pevent->port);
+  strcat(buf, buf2);
+
+  return buf;
+}
+#endif
+
+/* File Request Event - builds on Message Event */
+
+icq_FileRequestEvent *icq_FileRequestEventNew(int subtype,
+  unsigned long uin,  const char *message, const char *filename,
+  unsigned long filesize)
+{
+  new_event(p, icq_FileRequestEvent);
+  icq_Event *pbase=(icq_Event *)p;
+  icq_MessageEventInit((icq_MessageEvent *)p, ICQ_TCP_MSG_FILE, subtype,
+    uin, ICQ_TCP_MSG_REAL, message);
+  p->filename=filename;
+  p->filesize=filesize;
+
+  pbase->createPacket=icq_FileRequestCreatePacket;
+
+#ifdef EVENT_DEBUG
+  pbase->eventName=icq_FileRequestEventName;
+  pbase->eventDump=icq_FileRequestEventDump;
+#endif
+
+  return p;
+}
+
+icq_Packet *icq_FileRequestCreatePacket(icq_Event *pbase, 
+  icq_TCPLink *plink)
+{
+  icq_FileRequestEvent *pevent=(icq_FileRequestEvent *)pbase;
+
+  /* create header and message data */
+  icq_Packet *p=icq_MessageCreatePacket(pbase, plink);
+
+  /* append file event data */
+  icq_PacketAppend32(p, htonl(pevent->port));
+  icq_PacketAppendString(p, pevent->filename);
+  icq_PacketAppend32(p, pevent->filesize);
+  icq_PacketAppend32(p, htoicql(pevent->port));
+
+  return p;
+}
+
+void icq_FileParsePacket(icq_Event *pbase, icq_Packet *p)
+{
+  icq_FileRequestEvent *pevent=(icq_FileRequestEvent *)pbase;
+  int port;
+
+  /* parse header and message data */
+  icq_MessageParsePacket(pbase, p);
+
+  /* parse file event data */
+  port=icq_PacketRead32(p);                 /* file listen port, network */
+  pevent->filename=icq_PacketReadString(p); /* filename text */
+  pevent->filesize=icq_PacketRead32(p);     /* total size */
+  (void)icq_PacketRead32(p);                /* file listen port, intel */
+
+  pevent->port=ntohl(port);
+}
+
+#ifdef EVENT_DEBUG
+const char *icq_FileRequestEventName(icq_Event *p)
+{
+  if (p->type==ICQ_EVENT_MESSAGE)
+    return "file request";
+  else if (p->type==ICQ_EVENT_ACK) {
+    icq_MessageEvent *pevent=(icq_MessageEvent *)p;
+    if (pevent->status==ICQ_TCP_STATUS_REFUSE)
+      return "file request refuse";
+    else
+      return "file request ack";
+  } else if (p->type==ICQ_EVENT_CANCEL) 
+    return "file request cancel";
+
+  return "unknown file request";
+}
+
+const char *icq_FileRequestEventDump(icq_Event *p)
+{
+  static char buf[255];
+  static char buf2[255];
+  icq_FileRequestEvent *pevent=(icq_FileRequestEvent *)p;
+
+  strcpy(buf, icq_MessageEventDump(p));
+  sprintf(buf2, ", port=%d, filename=\"%s\", filesize=%ld", pevent->port,
+    pevent->filename, pevent->filesize);
+  strcat(buf, buf2);
+
+  return buf;
+}
+#endif
+
+/* main packet parser */
+
+icq_Event *icq_ParsePacket(icq_Packet *p)
+{
+  /* FIXME */
+  icq_Event *pevent=(icq_Event *)malloc(sizeof(icq_FileRequestEvent));
+  pevent->direction=ICQ_EVENT_INCOMING;
+  pevent->time=time(0);
+
+  icq_EventParsePacket(pevent, p);
+
+  switch(pevent->type) {
+
+    case ICQ_TCP_MSG_MSG:
+      icq_MessageParsePacket(pevent, p);
+      break;
+    case ICQ_TCP_MSG_URL:
+      icq_URLParsePacket(pevent, p);
+      break;
+    case ICQ_TCP_MSG_CHAT:
+      icq_ChatParsePacket(pevent, p);
+      break;
+    case ICQ_TCP_MSG_FILE:
+      icq_FileParsePacket(pevent, p);
+      break;
+    default:
+      /* FIXME: log */
+      free(pevent);
+      pevent=0;
+      break;
+  }
+
+  /* FIXME: ensure no bytes are remaining */
+
+  return pevent;
+}
+
+#ifdef EVENT_DEBUG
+const char *icq_EventDump(icq_Event *pevent)
+{
+  static char buf[255];
+
+  sprintf("%s event sent to uin %ld { %s }", (pevent->eventName)(pevent),
+    pevent->uin, (pevent->eventDump)(pevent) );
+
+  return buf;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/icqevent.h	Tue Dec 19 10:08:29 2000 +0000
@@ -0,0 +1,148 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+/*
+ * $Id: icqevent.h 1319 2000-12-19 10:08:29Z warmenhoven $
+ *
+ * $Log$
+ * Revision 1.1  2000/12/19 10:08:29  warmenhoven
+ * Yay, new icqlib
+ *
+ * Revision 1.2  2000/06/15 18:54:09  bills
+ * added time attribute and handleEvent function pointer to icq_Event,
+ * renamed icq_ChatEvent to icq_ChatRequestEvent, renamed icq_FileEvent to
+ * icq_FileRequestEvent, added icq_URLEvent and related methods
+ *
+ * Revision 1.1  2000/06/15 15:27:39  bills
+ * committed for safekeeping - this code will soon replace stdpackets.c and
+ * greatly simplify tcphandle.c, as well as reducing code duplication in many
+ * places.  it provides a much more flexible framework for managing events
+ * and parsing and creating packets
+ *
+*/
+
+#ifndef _ICQEVENT_H
+#define _ICQEVENT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <time.h>
+
+#include "icqpacket.h"
+#include "tcplink.h"
+#include "stdpackets.h"
+
+#define EVENT_DEBUG
+
+#define ICQ_EVENT_MESSAGE                ICQ_TCP_MESSAGE
+#define ICQ_EVENT_ACK                    ICQ_TCP_ACK
+#define ICQ_EVENT_CANCEL                 ICQ_TCP_CANCEL
+
+#define ICQ_EVENT_INCOMING               1
+#define ICQ_EVENT_OUTGOING               2
+
+typedef struct icq_Event_s {
+
+  unsigned long version;
+  unsigned long id;
+  unsigned long uin;
+
+  int type;         /* chat, file, message, url */
+  int subtype;      /* message, ack, or cancel */
+
+  int direction;  
+  time_t time;
+
+  icq_Packet *(*createPacket)(struct icq_Event_s *, icq_TCPLink *);
+  void (*handleEvent)(struct icq_Event_s *, ICQLINK *);
+
+#ifdef EVENT_DEBUG
+  const char *(*eventName)(struct icq_Event_s *);
+  const char *(*eventDump)(struct icq_Event_s *);
+#endif
+
+} icq_Event;
+
+typedef struct icq_MessageEvent_s {
+
+  icq_Event event;
+
+  char *message;  /* must be non-const for url hack */
+  char *url;      /* hack so we can use same structure for url */
+  int status;
+  int type;
+
+} icq_MessageEvent;
+
+typedef struct icq_MessageEvent_s icq_URLEvent;
+
+typedef struct icq_ChatRequestEvent_s {
+
+  icq_MessageEvent message_event;
+
+  int port;
+
+} icq_ChatRequestEvent;
+
+typedef struct icq_FileRequestEvent_s {
+
+  icq_MessageEvent message_event;
+
+  const char *filename;
+  unsigned long filesize;
+  int port;
+
+} icq_FileRequestEvent;
+
+/* generic event functions */
+void icq_EventInit(icq_Event *p, int type, int subtype, unsigned long uin,
+  int version);
+icq_Packet *icq_EventCreatePacket(icq_Event *pbase);
+void icq_EventParsePacket(icq_Event *pevent, icq_Packet *p);
+
+/* message event functions */
+icq_MessageEvent *icq_CreateMessageEvent(int subtype, unsigned long uin, 
+  const char *message);
+void icq_MessageEventInit(icq_MessageEvent *p, int type, int subtype, 
+  unsigned long uin, int msgtype, const char *message);
+icq_Packet *icq_MessageCreatePacket(icq_Event *pbase, icq_TCPLink *plink);
+void icq_MessageParsePacket(icq_Event *pbase, icq_Packet *p);
+
+/* url event functions */
+icq_URLEvent *icq_CreateURLEvent(int subtype, unsigned long uin, 
+  const char *message, const char *url);
+icq_Packet *icq_URLCreatePacket(icq_Event *pbase, icq_TCPLink *plink);
+void icq_URLParsePacket(icq_Event *pbase, icq_Packet *p);
+
+/* chat request event functions */
+icq_ChatRequestEvent *icq_ChatRequestEventNew(int subtype, 
+  unsigned long uin, const char *message, int port);
+icq_Packet *icq_ChatRequestCreatePacket(icq_Event *pbase,
+  icq_TCPLink *plink);
+void icq_ChatParsePacket(icq_Event *pbase, icq_Packet *p);
+
+/* file request event functions */
+icq_FileRequestEvent *icq_FileRequestEventNew(int subtype,
+  unsigned long uin, const char *message, const char *filename,
+  unsigned long filesize);
+icq_Packet *icq_FileRequestCreatePacket(icq_Event *pbase,
+  icq_TCPLink *plink);
+void icq_FileParsePacket(icq_Event *pbase, icq_Packet *p);
+
+/* main packet parser */
+icq_Event *icq_ParsePacket(icq_Packet *p);
+
+#ifdef EVENT_DEBUG
+const char *icq_MessageEventName(icq_Event *p);
+const char *icq_MessageEventDump(icq_Event *p);
+const char *icq_URLEventName(icq_Event *p);
+const char *icq_URLEventDump(icq_Event *p);
+const char *icq_ChatRequestEventName(icq_Event *p);
+const char *icq_ChatRequestEventDump(icq_Event *p);
+const char *icq_FileRequestEventName(icq_Event *p);
+const char *icq_FileRequestEventDump(icq_Event *p);
+const char *icq_EventDump(icq_Event *p);
+#endif
+
+#endif /* _ICQEVENT_H */
--- a/plugins/icq/icqlib.c	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/icqlib.c	Tue Dec 19 10:08:29 2000 +0000
@@ -1,9 +1,15 @@
 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
-$Id: icqlib.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Id: icqlib.c 1319 2000-12-19 10:08:29Z warmenhoven $
 $Log$
-Revision 1.1  2000/11/28 02:22:42  warmenhoven
-icq. whoop de doo
+Revision 1.2  2000/12/19 10:08:29  warmenhoven
+Yay, new icqlib
+
+Revision 1.46  2000/12/19 06:00:07  bills
+moved members from ICQLINK to ICQLINK_private struct
+
+Revision 1.45  2000/11/02 07:29:07  denis
+Ability to disable TCP protocol has been added.
 
 Revision 1.44  2000/07/24 03:10:08  bills
 added support for real nickname during TCP transactions like file and
@@ -209,10 +215,14 @@
   return 0;
 }
 
-void icq_Init(ICQLINK *link, DWORD uin, const char *password,
-  const char *nick)
+ICQLINK *icq_ICQLINKNew(DWORD uin, const char *password, const char *nick,
+  unsigned char useTCP)
 {
+  ICQLINK *link = (ICQLINK *)malloc(sizeof(ICQLINK));
+  link->d = (ICQLINK_private *)malloc(sizeof(ICQLINK_private));
+
   srand(time(0L));
+
 /*   memset(link, 0, sizeof(ICQLINK)); */
 
   /* Initialize all callbacks */
@@ -255,18 +265,19 @@
   link->icq_Nick = strdup(nick);
   link->icq_OurIP = -1;
   link->icq_OurPort = 0;
-  link->icq_ContactList = list_new();
+  link->d->icq_ContactList = list_new();
   link->icq_Status = -1;
 
   /* UDP stuff */
   link->icq_UDPSok = -1;
-  memset(link->icq_UDPServMess, FALSE, sizeof(link->icq_UDPServMess));
-  link->icq_UDPSeqNum1 = 0;
-  link->icq_UDPSeqNum2 = 0;
-  link->icq_UDPSession = 0;
+  memset(link->d->icq_UDPServMess, FALSE, sizeof(link->d->icq_UDPServMess));
+  link->d->icq_UDPSeqNum1 = 0;
+  link->d->icq_UDPSeqNum2 = 0;
+  link->d->icq_UDPSession = 0;
   icq_UDPQueueNew(link);
 
   icq_TCPInit(link);
+  link->icq_UseTCP = useTCP;
 
   /* Proxy stuff */
   link->icq_UseProxy = 0;
@@ -280,18 +291,22 @@
   link->icq_ProxyOurPort = 0;
   link->icq_ProxyDestIP = -1;
   link->icq_ProxyDestPort = 0;
+
+  return link;
 }
 
-void icq_Done(ICQLINK *link)
+void icq_ICQLINKDelete(ICQLINK *link)
 {
   icq_TCPDone(link);
   if(link->icq_Password)
     free(link->icq_Password);
   if(link->icq_Nick)
     free(link->icq_Nick);
-  if(link->icq_ContactList)
-    list_delete(link->icq_ContactList, icq_ContactDelete);
+  if(link->d->icq_ContactList)
+    list_delete(link->d->icq_ContactList, icq_ContactDelete);
   icq_UDPQueueDelete(link);
+  free(link->d);
+  free(link);
 }
 
 /******************************
@@ -607,12 +622,12 @@
 *************************/
 BOOL icq_GetServMess(ICQLINK *link, WORD num)
 {
-  return ((link->icq_UDPServMess[num/8] & (1 << (num%8))) >> (num%8));
+  return ((link->d->icq_UDPServMess[num/8] & (1 << (num%8))) >> (num%8));
 }
 
 void icq_SetServMess(ICQLINK *link, WORD num)
 {
-  link->icq_UDPServMess[num/8] |= (1 << (num%8));
+  link->d->icq_UDPServMess[num/8] |= (1 << (num%8));
 }
 
 int icq_GetSok(ICQLINK *link)
--- a/plugins/icq/icqlib.h	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/icqlib.h	Tue Dec 19 10:08:29 2000 +0000
@@ -42,4 +42,30 @@
 #endif /* strdup */
 #endif /* _WIN32 */
 
+/** Private ICQLINK data.  These are members that are internal to
+ * icqlib, but must be contained in the per-connection ICQLINK
+ * struct.
+ */
+typedef struct icq_link_private {
+
+  void *icq_ContactList;
+
+  /* 65536 seqs max, 1 bit per seq -> 65536/8 = 8192 */
+  unsigned char icq_UDPServMess[8192]; 
+
+  unsigned short icq_UDPSeqNum1, icq_UDPSeqNum2;
+  unsigned long icq_UDPSession;
+  
+  void *icq_UDPQueue;
+
+  int icq_TCPSequence;
+  void *icq_TCPLinks;
+  void *icq_ChatSessions;
+  void *icq_FileSessions;
+  int TCP_maxfd;
+  fd_set TCP_readfds;
+  fd_set TCP_writefds;
+
+} ICQLINK_private;
+
 #endif /* _ICQLIB_H_ */
--- a/plugins/icq/icqpacket.c	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/icqpacket.c	Tue Dec 19 10:08:29 2000 +0000
@@ -1,9 +1,9 @@
 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
-$Id: icqpacket.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Id: icqpacket.c 1319 2000-12-19 10:08:29Z warmenhoven $
 $Log$
-Revision 1.1  2000/11/28 02:22:42  warmenhoven
-icq. whoop de doo
+Revision 1.2  2000/12/19 10:08:29  warmenhoven
+Yay, new icqlib
 
 Revision 1.10  2000/07/07 15:26:35  denis
 "icq_Packet data overflow" log message temporarily commented out.
--- a/plugins/icq/list.c	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/list.c	Tue Dec 19 10:08:29 2000 +0000
@@ -1,9 +1,9 @@
 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
-$Id: list.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Id: list.c 1319 2000-12-19 10:08:29Z warmenhoven $
 $Log$
-Revision 1.1  2000/11/28 02:22:42  warmenhoven
-icq. whoop de doo
+Revision 1.2  2000/12/19 10:08:29  warmenhoven
+Yay, new icqlib
 
 Revision 1.14  2000/07/10 01:44:20  bills
 i really don't learn - removed LIST_TRACE define
--- a/plugins/icq/proxy.c	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/proxy.c	Tue Dec 19 10:08:29 2000 +0000
@@ -1,9 +1,9 @@
 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
-$Id: proxy.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Id: proxy.c 1319 2000-12-19 10:08:29Z warmenhoven $
 $Log$
-Revision 1.1  2000/11/28 02:22:42  warmenhoven
-icq. whoop de doo
+Revision 1.2  2000/12/19 10:08:29  warmenhoven
+Yay, new icqlib
 
 Revision 1.8  2000/05/10 18:51:23  denis
 icq_Disconnect() now called before icq_Disconnected callback to
--- a/plugins/icq/queue.c	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/queue.c	Tue Dec 19 10:08:29 2000 +0000
@@ -1,12 +1,19 @@
 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
-$Id: queue.c 1202 2000-12-04 06:22:48Z robflynn $
+$Id: queue.c 1319 2000-12-19 10:08:29Z warmenhoven $
 $Log$
-Revision 1.2  2000/12/04 06:22:48  robflynn
-Da numba one stunna!
+Revision 1.3  2000/12/19 10:08:29  warmenhoven
+Yay, new icqlib
+
+Revision 1.12  2000/12/19 06:00:07  bills
+moved members from ICQLINK to ICQLINK_private struct
 
-Revision 1.1  2000/11/28 02:22:42  warmenhoven
-icq. whoop de doo
+Revision 1.11  2000/12/06 05:15:45  denis
+Handling for mass TCP messages has been added based on patch by
+Konstantin Klyagin <konst@konst.org.ua>
+
+Revision 1.10  2000/12/03 21:56:38  bills
+fixed compilation with gcc-2.96
 
 Revision 1.9  2000/07/10 01:31:17  bills
 oops - removed #define LIST_TRACE and #define QUEUE_DEBUG
@@ -44,12 +51,13 @@
 #include <stdlib.h>
 #include <time.h>
 
+#include "icqlib.h"
 #include "queue.h"
 #include "list.h"
 
 void icq_UDPQueueNew(ICQLINK *link)
 {
-  link->icq_UDPQueue = list_new();
+  link->d->icq_UDPQueue = list_new();
   link->icq_UDPExpireInterval = 15; /* expire interval = 15 sec */
 }
 
@@ -66,17 +74,17 @@
 #ifdef QUEUE_DEBUG
   printf("enqueuing queueitem %p\n", ptr);
 #endif
-  list_enqueue(link->icq_UDPQueue, ptr);
+  list_enqueue(link->d->icq_UDPQueue, ptr);
 }
 
 icq_Packet *icq_UDPQueueGet(ICQLINK *link)
 {
-  icq_UDPQueueItem *ptr = (icq_UDPQueueItem*)list_first(link->icq_UDPQueue);
+  icq_UDPQueueItem *ptr = (icq_UDPQueueItem*)list_first(link->d->icq_UDPQueue);
   icq_Packet *pack = 0L;
   if(ptr)
   {
     pack = ptr->pack;
-    list_remove(link->icq_UDPQueue, (list_node*)ptr);
+    list_remove(link->d->icq_UDPQueue, (list_node*)ptr);
   }
 #ifdef QUEUE_DEBUG
   if(pack)
@@ -87,7 +95,7 @@
 
 icq_Packet *icq_UDPQueuePeek(ICQLINK *link)
 {
-  icq_UDPQueueItem *ptr = (icq_UDPQueueItem*)list_first(link->icq_UDPQueue);
+  icq_UDPQueueItem *ptr = (icq_UDPQueueItem*)list_first(link->d->icq_UDPQueue);
   if(ptr)
     return ptr->pack;
   else
@@ -114,10 +122,10 @@
 #ifdef QUEUE_DEBUG
   printf("icq_UDPQueueDelete\n");
 #endif
-  if(link->icq_UDPQueue)
+  if(link->d->icq_UDPQueue)
   {
-    list_delete(link->icq_UDPQueue, _icq_UDPQueueItemFree);
-    link->icq_UDPQueue = 0;
+    list_delete(link->d->icq_UDPQueue, _icq_UDPQueueItemFree);
+    link->d->icq_UDPQueue = 0;
   }
 }
 
@@ -127,8 +135,8 @@
 #ifdef QUEUE_DEBUG
   printf("icq_UDPQueueFree\n");
 #endif
-  if(link->icq_UDPQueue)
-    list_free(link->icq_UDPQueue, _icq_UDPQueueItemFree);
+  if(link->d->icq_UDPQueue)
+    list_free(link->d->icq_UDPQueue, _icq_UDPQueueItemFree);
 }
 
 int icq_UDPQueueFindSeq(void *p, va_list data)
@@ -143,13 +151,13 @@
 #ifdef QUEUE_DEBUG
   printf("icq_UDPQueueDelSeq(seq=0x%04X", seq);
 #endif
-  ptr = list_traverse(link->icq_UDPQueue, icq_UDPQueueFindSeq, seq);
+  ptr = list_traverse(link->d->icq_UDPQueue, icq_UDPQueueFindSeq, seq);
   if(ptr)
   {
 #ifdef QUEUE_DEBUG
     printf(", cmd=0x%04X",icq_PacketReadUDPOutCmd(ptr->pack));
 #endif
-    list_remove(link->icq_UDPQueue, ptr);
+    list_remove(link->d->icq_UDPQueue, ptr);
     _icq_UDPQueueItemFree(ptr);
   }
 #ifdef QUEUE_DEBUG
@@ -160,7 +168,7 @@
 long icq_UDPQueueInterval(ICQLINK *link)
 {
   long interval;
-  icq_UDPQueueItem *ptr = (icq_UDPQueueItem*)list_first(link->icq_UDPQueue);
+  icq_UDPQueueItem *ptr = (icq_UDPQueueItem*)list_first(link->d->icq_UDPQueue);
   if(ptr)
   {
     interval = ptr->expire - time(0L);
--- a/plugins/icq/stdpackets.c	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/stdpackets.c	Tue Dec 19 10:08:29 2000 +0000
@@ -1,9 +1,12 @@
 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
-$Id: stdpackets.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Id: stdpackets.c 1319 2000-12-19 10:08:29Z warmenhoven $
 $Log$
-Revision 1.1  2000/11/28 02:22:42  warmenhoven
-icq. whoop de doo
+Revision 1.2  2000/12/19 10:08:29  warmenhoven
+Yay, new icqlib
+
+Revision 1.11  2000/12/19 06:00:07  bills
+moved members from ICQLINK to ICQLINK_private struct
 
 Revision 1.10  2000/06/15 01:51:23  bills
 added creation functions for cancel and refuse operations
@@ -380,7 +383,7 @@
 
 void icq_TCPAppendSequence(ICQLINK *link, icq_Packet *p)
 {
-  p->id=link->icq_TCPSequence--;
+  p->id=link->d->icq_TCPSequence--;
   icq_PacketEnd(p);
   icq_PacketAppend32(p, p->id);
 }
@@ -529,18 +532,18 @@
 {
   icq_Packet *p = icq_PacketNew();
 
-/*  if(!link->icq_UDPSession)
-    link->icq_UDPSession = rand() & 0x3FFFFFFF;
-  if(!link->icq_UDPSeqNum2)
-    link->icq_UDPSeqNum2 = rand() & 0x7FFF;*/
+/*  if(!link->d->icq_UDPSession)
+    link->d->icq_UDPSession = rand() & 0x3FFFFFFF;
+  if(!link->d->icq_UDPSeqNum2)
+    link->d->icq_UDPSeqNum2 = rand() & 0x7FFF;*/
 
   icq_PacketAppend16(p, ICQ_UDP_VER);            /* ver */
   icq_PacketAppend32(p, 0);                      /* zero */
   icq_PacketAppend32(p, link->icq_Uin);          /* uin */
-  icq_PacketAppend32(p, link->icq_UDPSession);   /* session */
+  icq_PacketAppend32(p, link->d->icq_UDPSession);   /* session */
   icq_PacketAppend16(p, cmd);                    /* cmd */
-  icq_PacketAppend16(p, link->icq_UDPSeqNum1++); /* seq1 */
-  icq_PacketAppend16(p, link->icq_UDPSeqNum2++); /* seq2 */
+  icq_PacketAppend16(p, link->d->icq_UDPSeqNum1++); /* seq1 */
+  icq_PacketAppend16(p, link->d->icq_UDPSeqNum2++); /* seq2 */
   icq_PacketAppend32(p, 0);                      /* checkcode */
 
   return p;
@@ -553,7 +556,7 @@
   icq_PacketAppend16(p, ICQ_UDP_VER);            /* ver */
   icq_PacketAppend32(p, 0);                      /* zero */
   icq_PacketAppend32(p, link->icq_Uin);          /* uin */
-  icq_PacketAppend32(p, link->icq_UDPSession);   /* session */
+  icq_PacketAppend32(p, link->d->icq_UDPSession);   /* session */
   icq_PacketAppend16(p, cmd);                    /* cmd */
   icq_PacketAppend16(p, seq);                    /* seq1 */
   icq_PacketAppend16(p, 0);                      /* seq2 */
--- a/plugins/icq/stdpackets.h	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/stdpackets.h	Tue Dec 19 10:08:29 2000 +0000
@@ -25,6 +25,7 @@
 #define ICQ_TCP_MSG_READNA       0x03EA
 #define ICQ_TCP_MSG_READDND      0x03EB
 #define ICQ_TCP_MSG_READFFC      0x03EC
+#define ICQ_TCP_MASS_MASK        0x8000
 
 /* TCP Message Command Types */
 #define ICQ_TCP_MSG_ACK          0x0000
--- a/plugins/icq/tcp.c	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/tcp.c	Tue Dec 19 10:08:29 2000 +0000
@@ -1,9 +1,12 @@
 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
-$Id: tcp.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Id: tcp.c 1319 2000-12-19 10:08:29Z warmenhoven $
 $Log$
-Revision 1.1  2000/11/28 02:22:42  warmenhoven
-icq. whoop de doo
+Revision 1.2  2000/12/19 10:08:29  warmenhoven
+Yay, new icqlib
+
+Revision 1.37  2000/12/19 06:00:07  bills
+moved members from ICQLINK to ICQLINK_private struct
 
 Revision 1.36  2000/07/09 22:19:35  bills
 added new *Close functions, use *Close functions instead of *Delete
@@ -167,9 +170,9 @@
   icq_TCPLink *plink;
 
   /* allocate lists */
-  link->icq_TCPLinks=list_new();
-  link->icq_ChatSessions=list_new();
-  link->icq_FileSessions=list_new();
+  link->d->icq_TCPLinks=list_new();
+  link->d->icq_ChatSessions=list_new();
+  link->d->icq_FileSessions=list_new();
 
   /* only the main listening socket gets created upon initialization -
    * the other two are created when necessary */
@@ -178,7 +181,7 @@
   link->icq_TCPSrvPort=ntohs(plink->socket_address.sin_port);
 
   /* reset tcp sequence number */
-  link->icq_TCPSequence=0xfffffffe;
+  link->d->icq_TCPSequence=0xfffffffe;
 
   return 0;
 }
@@ -187,9 +190,9 @@
 {
   /* close and deallocate all tcp links, this will also close any attached 
    * file or chat sessions */
-  list_delete(link->icq_TCPLinks, icq_TCPLinkDelete);
-  list_delete(link->icq_ChatSessions, icq_ChatSessionDelete);
-  list_delete(link->icq_FileSessions, icq_FileSessionDelete);
+  list_delete(link->d->icq_TCPLinks, icq_TCPLinkDelete);
+  list_delete(link->d->icq_ChatSessions, icq_ChatSessionDelete);
+  list_delete(link->d->icq_FileSessions, icq_FileSessionDelete);
 }
 
 /* helper function for icq_TCPMain */
@@ -204,19 +207,19 @@
   {
     int socket=plink->socket;
 
-    FD_SET(socket, &icqlink->TCP_readfds);
+    FD_SET(socket, &icqlink->d->TCP_readfds);
 
     /* we only care about writing if socket is trying to connect */
     if(plink->mode & TCP_LINK_MODE_CONNECTING)
     {
       if(plink->mode & (TCP_LINK_SOCKS_AUTHORIZATION | TCP_LINK_SOCKS_NOAUTHSTATUS | TCP_LINK_SOCKS_AUTHSTATUS | TCP_LINK_SOCKS_CONNSTATUS))
-        FD_SET(socket, &icqlink->TCP_readfds);
+        FD_SET(socket, &icqlink->d->TCP_readfds);
       else
-        FD_SET(socket, &icqlink->TCP_writefds);
+        FD_SET(socket, &icqlink->d->TCP_writefds);
     }
 
-    if(socket+1>icqlink->TCP_maxfd)
-      icqlink->TCP_maxfd=socket+1;
+    if(socket+1>icqlink->d->TCP_maxfd)
+      icqlink->d->TCP_maxfd=socket+1;
   }
 
   return 0; /* traverse the entire list */
@@ -234,7 +237,7 @@
   /* handle connecting sockets */
   if (plink->mode & TCP_LINK_MODE_CONNECTING)
   {
-    if(socket>-1 && (FD_ISSET(socket, &icqlink->TCP_writefds) || FD_ISSET(socket, &icqlink->TCP_readfds)))
+    if(socket>-1 && (FD_ISSET(socket, &icqlink->d->TCP_writefds) || FD_ISSET(socket, &icqlink->d->TCP_readfds)))
     {
       icq_TCPLinkOnConnect(plink);
       return 0; 
@@ -249,7 +252,7 @@
 
   /* handle ready for read sockets- either a connection is waiting on *
    * the listen sockets or data is ready to be read */
-  if(socket>-1 && FD_ISSET(socket, &icqlink->TCP_readfds))
+  if(socket>-1 && FD_ISSET(socket, &icqlink->d->TCP_readfds))
   {
     if(plink->mode & TCP_LINK_MODE_LISTEN)
       (void)icq_TCPLinkAccept(plink);
@@ -295,23 +298,23 @@
   tv.tv_sec = 0;
   tv.tv_usec = 0;
 
-  link->TCP_maxfd = 0;
-  FD_ZERO(&link->TCP_readfds);
-  FD_ZERO(&link->TCP_writefds);
+  link->d->TCP_maxfd = 0;
+  FD_ZERO(&link->d->TCP_readfds);
+  FD_ZERO(&link->d->TCP_writefds);
 
   /* generate the fd sets for all open tcp links */
-  (void)list_traverse(link->icq_TCPLinks, _generate_fds);
+  (void)list_traverse(link->d->icq_TCPLinks, _generate_fds);
 
   /* determine which sockets require maintenance */
-  select(link->TCP_maxfd, &link->TCP_readfds, &link->TCP_writefds, 0, &tv);
+  select(link->d->TCP_maxfd, &link->d->TCP_readfds, &link->d->TCP_writefds, 0, &tv);
 
   /* call icq_TCPLinkOnDataReceived for any sockets with ready data,
    * send all packets on send queue if socket has connected, and
    * accept() from any listening sockets with pending connections */ 
-  (void)list_traverse(link->icq_TCPLinks, _handle_ready_sockets, 0, 0);
+  (void)list_traverse(link->d->icq_TCPLinks, _handle_ready_sockets, 0, 0);
 
   /* process all packets waiting for each TCPLink */
-  (void)list_traverse(link->icq_TCPLinks, _process_links, 0, 0);
+  (void)list_traverse(link->d->icq_TCPLinks, _process_links, 0, 0);
 }
 
 icq_TCPLink *icq_TCPCheckLink(ICQLINK *link, DWORD uin, int type)
--- a/plugins/icq/tcp.h	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/tcp.h	Tue Dec 19 10:08:29 2000 +0000
@@ -25,13 +25,13 @@
 
 /* Debugging */
 /* trace packet process results */
-/* #define TCP_PROCESS_TRACE */
+#undef TCP_PROCESS_TRACE 
 
 /* trace sent and received icq packets */
-/* #define TCP_PACKET_TRACE     */
+#undef TCP_PACKET_TRACE    
 
 /* trace raw sent and received packet data */
-/* #define TCP_RAW_TRACE  */
+#undef TCP_RAW_TRACE 
 
 /* trace recv buffer in tcplink.c*/
 #undef TCP_BUFFER_TRACE
--- a/plugins/icq/tcpchathandle.c	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/tcpchathandle.c	Tue Dec 19 10:08:29 2000 +0000
@@ -1,9 +1,9 @@
 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
-$Id: tcpchathandle.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Id: tcpchathandle.c 1319 2000-12-19 10:08:29Z warmenhoven $
 $Log$
-Revision 1.1  2000/11/28 02:22:42  warmenhoven
-icq. whoop de doo
+Revision 1.2  2000/12/19 10:08:29  warmenhoven
+Yay, new icqlib
 
 Revision 1.8  2000/07/24 03:10:08  bills
 added support for real nickname during TCP transactions like file and
--- a/plugins/icq/tcpfilehandle.c	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/tcpfilehandle.c	Tue Dec 19 10:08:29 2000 +0000
@@ -1,9 +1,9 @@
 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
-$Id: tcpfilehandle.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Id: tcpfilehandle.c 1319 2000-12-19 10:08:29Z warmenhoven $
 $Log$
-Revision 1.1  2000/11/28 02:22:42  warmenhoven
-icq. whoop de doo
+Revision 1.2  2000/12/19 10:08:29  warmenhoven
+Yay, new icqlib
 
 Revision 1.15  2000/07/24 03:10:08  bills
 added support for real nickname during TCP transactions like file and
--- a/plugins/icq/tcphandle.c	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/tcphandle.c	Tue Dec 19 10:08:29 2000 +0000
@@ -1,9 +1,16 @@
 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
-$Id: tcphandle.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Id: tcphandle.c 1319 2000-12-19 10:08:29Z warmenhoven $
 $Log$
-Revision 1.1  2000/11/28 02:22:42  warmenhoven
-icq. whoop de doo
+Revision 1.2  2000/12/19 10:08:29  warmenhoven
+Yay, new icqlib
+
+Revision 1.14  2000/12/06 05:15:45  denis
+Handling for mass TCP messages has been added based on patch by
+Konstantin Klyagin <konst@konst.org.ua>
+
+Revision 1.13  2000/08/13 19:44:41  denis
+Cyrillic recoding on received URL description added.
 
 Revision 1.12  2000/07/09 22:19:35  bills
 added new *Close functions, use *Close functions instead of *Delete
@@ -133,7 +140,7 @@
   status=icq_PacketRead16(p);
   command_type=icq_PacketRead16(p);
 
-  switch(type)
+  switch(type & ~ICQ_TCP_MASS_MASK)
   {
     case ICQ_TCP_MSG_MSG:
     case ICQ_TCP_MSG_URL:
@@ -172,7 +179,7 @@
   switch(command)
   {
     case ICQ_TCP_MESSAGE:
-      switch(type)
+      switch(type & ~ICQ_TCP_MASS_MASK)
       {
         case ICQ_TCP_MSG_MSG:
           icq_TCPOnMessageReceived(plink->icqlink, uin, message, p->id, plink);
@@ -197,7 +204,8 @@
       break;
 
     case ICQ_TCP_ACK:
-      switch(type) {
+      switch(type)
+      {
         case ICQ_TCP_MSG_CHAT:
           icq_HandleChatAck(plink, p, port);
           break;
@@ -208,14 +216,15 @@
 
         case ICQ_TCP_MSG_MSG:
         case ICQ_TCP_MSG_URL:
-          if(plink->icqlink->icq_RequestNotify) {
+          if(plink->icqlink->icq_RequestNotify)
+          {
             icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, "received ack %d\n", p->id);
             (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_ACK, status,
                                                (void *)message);
             (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_SUCCESS, 0, 0);
           }
           break;
-      }        
+      }
       break;
 
     case ICQ_TCP_CANCEL:
@@ -224,7 +233,7 @@
 
     default:
       icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, 
-			  "unknown packet command %d!\n", command);
+                 "unknown packet command %d!\n", command);
   }
 }
 
@@ -240,7 +249,7 @@
 }
 
 int icq_TCPProcessHello(icq_Packet *p, icq_TCPLink *plink)
-{	
+{
   /* TCP Hello packet */
   BYTE code;                /* 0xFF - init packet code */
   DWORD version;            /* tcp version */
@@ -337,8 +346,8 @@
      uin, id);
 #endif /*TCP_PACKET_TRACE*/
 
-  if(link->icq_RecvURL) {
-
+  if(link->icq_RecvURL)
+  {
     /* use the current system time for time received */
     time_t t=time(0);
     struct tm *ptime=localtime(&t);
@@ -349,6 +358,7 @@
     /* the URL is split from the description by 0xFE */
     pfe=strchr(message, '\xFE');
     *pfe=0;
+    icq_RusConv("wk", (char*)message);
     (*link->icq_RecvURL)(link, uin, ptime->tm_hour, ptime->tm_min,
        ptime->tm_mday, ptime->tm_mon+1, ptime->tm_year+1900, pfe+1, message);
 
@@ -362,5 +372,3 @@
     icq_PacketDelete(pack);
   }
 }
-
-
--- a/plugins/icq/tcplink.c	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/tcplink.c	Tue Dec 19 10:08:29 2000 +0000
@@ -1,9 +1,15 @@
 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
-$Id: tcplink.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Id: tcplink.c 1319 2000-12-19 10:08:29Z warmenhoven $
 $Log$
-Revision 1.1  2000/11/28 02:22:42  warmenhoven
-icq. whoop de doo
+Revision 1.2  2000/12/19 10:08:29  warmenhoven
+Yay, new icqlib
+
+Revision 1.40  2000/12/19 06:00:07  bills
+moved members from ICQLINK to ICQLINK_private struct
+
+Revision 1.39  2000/12/03 21:57:15  bills
+fixed bug #105068
 
 Revision 1.38  2000/07/09 22:19:35  bills
 added new *Close functions, use *Close functions instead of *Delete
@@ -196,7 +202,7 @@
   p->proxy_status = 0;
 
   if(p)
-    list_enqueue(link->icq_TCPLinks, p);
+    list_enqueue(link->d->icq_TCPLinks, p);
 
   return p;
 }
@@ -267,7 +273,7 @@
 
 void icq_TCPLinkClose(icq_TCPLink *plink)
 {
-  list_remove(plink->icqlink->icq_TCPLinks, plink);
+  list_remove(plink->icqlink->d->icq_TCPLinks, plink);
   icq_TCPLinkDelete(plink);
 }
 
@@ -776,7 +782,6 @@
         icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "tcplink buffer "
           "overflow, packet size = %d, buffer size = %d, closing link\n",
           packet_size, icq_TCPLinkBufferSize);
-        icq_TCPLinkClose(plink);
         return 0;
       }
 
@@ -924,7 +929,7 @@
 {
   /* append the next sequence number on the packet */
   if (!sequence)
-    sequence=plink->icqlink->icq_TCPSequence--;
+    sequence=plink->icqlink->d->icq_TCPSequence--;
   p->id=sequence;
   icq_PacketEnd(p);
   icq_PacketAppend32(p, sequence);
@@ -1010,5 +1015,5 @@
 
 icq_TCPLink *icq_FindTCPLink(ICQLINK *link, unsigned long uin, int type)
 {
-  return list_traverse(link->icq_TCPLinks, _icq_FindTCPLink, uin, type);
+  return list_traverse(link->d->icq_TCPLinks, _icq_FindTCPLink, uin, type);
 }
--- a/plugins/icq/udp.c	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/udp.c	Tue Dec 19 10:08:29 2000 +0000
@@ -1,9 +1,18 @@
 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
-$Id: udp.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Id: udp.c 1319 2000-12-19 10:08:29Z warmenhoven $
 $Log$
-Revision 1.1  2000/11/28 02:22:42  warmenhoven
-icq. whoop de doo
+Revision 1.2  2000/12/19 10:08:29  warmenhoven
+Yay, new icqlib
+
+Revision 1.26  2000/12/19 06:00:07  bills
+moved members from ICQLINK to ICQLINK_private struct
+
+Revision 1.25  2000/11/02 07:29:07  denis
+Ability to disable TCP protocol has been added.
+
+Revision 1.24  2000/08/13 00:59:52  denis
+Patch #101057 have been applied.
 
 Revision 1.23  2000/07/09 22:19:35  bills
 added new *Close functions, use *Close functions instead of *Delete
@@ -297,7 +306,7 @@
   int attempt;
   while(icq_UDPQueueInterval(link) == 0)
   {
-    ptr = (icq_UDPQueueItem*)list_first(link->icq_UDPQueue);
+    ptr = (icq_UDPQueueItem*)list_first(link->d->icq_UDPQueue);
     attempt = ptr->attempts + 1;
     if(attempt > 6)
     {
@@ -325,7 +334,7 @@
 *****************************************/
 WORD icq_KeepAlive(ICQLINK *link) /* V5 */
 {
-  icq_Packet *p = icq_UDPCreateStdSeqPacket(link, UDP_CMD_KEEP_ALIVE, link->icq_UDPSeqNum1++);
+  icq_Packet *p = icq_UDPCreateStdSeqPacket(link, UDP_CMD_KEEP_ALIVE, link->d->icq_UDPSeqNum1++);
   icq_PacketAppend32(p, rand());
   icq_UDPSockWrite(link, p);
   icq_PacketDelete(p);
@@ -339,7 +348,7 @@
 
   icq_FmtLog(link, ICQ_LOG_MESSAGE, "Send Keep Alive packet to the server\n");
 
-  return link->icq_UDPSeqNum1-1;
+  return link->d->icq_UDPSeqNum1-1;
 }
 
 /**********************************
@@ -467,10 +476,10 @@
 {
   icq_Packet *p;
 
-  memset(link->icq_UDPServMess, FALSE, sizeof(link->icq_UDPServMess));
-  link->icq_UDPSession = rand() & 0x3FFFFFFF;
-  link->icq_UDPSeqNum1 = rand() & 0x7FFF;
-  link->icq_UDPSeqNum2 = 1;
+  memset(link->d->icq_UDPServMess, FALSE, sizeof(link->d->icq_UDPServMess));
+  link->d->icq_UDPSession = rand() & 0x3FFFFFFF;
+  link->d->icq_UDPSeqNum1 = rand() & 0x7FFF;
+  link->d->icq_UDPSeqNum2 = 1;
 
   p = icq_UDPCreateStdPacket(link, UDP_CMD_LOGIN);
   icq_PacketAppend32(p, time(0L));
@@ -479,11 +488,24 @@
   icq_PacketAppend16n(p, htons(link->icq_OurPort));*/
   icq_PacketAppendString(p, link->icq_Password);
   icq_PacketAppend32(p, LOGIN_X1_DEF);
-  icq_PacketAppend32n(p, htonl(link->icq_OurIP));
-  if(link->icq_UseProxy)
-    icq_PacketAppend8(p, LOGIN_SNDONLY_TCP);
+  if(link->icq_UseTCP)
+  {
+    if(link->icq_UseProxy)
+    {
+      icq_PacketAppend32n(p, htonl(link->icq_ProxyIP));
+      icq_PacketAppend8(p, LOGIN_SNDONLY_TCP);
+    }
+    else
+    {
+      icq_PacketAppend32n(p, htonl(link->icq_OurIP));
+      icq_PacketAppend8(p, LOGIN_SNDRCV_TCP);
+    }
+  }
   else
-    icq_PacketAppend8(p, LOGIN_SNDRCV_TCP);
+  {
+    icq_PacketAppend32n(p, htonl(link->icq_ProxyIP));
+    icq_PacketAppend8(p, LOGIN_NO_TCP);
+  }
   icq_PacketAppend32(p, status);
   icq_PacketAppend32(p, LOGIN_X3_DEF);
   icq_PacketAppend32(p, LOGIN_X4_DEF);
@@ -498,7 +520,7 @@
 ***********************/
 void icq_Logout(ICQLINK *link) /* V5 */
 {
-  icq_Packet *p = icq_UDPCreateStdSeqPacket(link, UDP_CMD_SEND_TEXT_CODE, link->icq_UDPSeqNum1++);
+  icq_Packet *p = icq_UDPCreateStdSeqPacket(link, UDP_CMD_SEND_TEXT_CODE, link->d->icq_UDPSeqNum1++);
   icq_PacketAppendString(p, "B_USER_DISCONNECTED");
   icq_PacketAppend8(p, 5);
   icq_PacketAppend8(p, 0);
@@ -540,7 +562,7 @@
 
   icq_UDPSockWrite(link, p);
   icq_PacketDelete(p);
-  return link->icq_UDPSeqNum1-1;
+  return link->d->icq_UDPSeqNum1-1;
 }
 
 WORD icq_UDPSendURL(ICQLINK *link, DWORD uin, const char *url, const char *descr) /* V5 */
@@ -561,7 +583,7 @@
 
   icq_UDPSockWrite(link, p);
   icq_PacketDelete(p);
-  return link->icq_UDPSeqNum1-1;
+  return link->d->icq_UDPSeqNum1-1;
 }
 
 /**************************************************
@@ -577,7 +599,7 @@
   icq_UDPSockWrite(link, p);
   icq_PacketDelete(p);
 
-  return link->icq_UDPSeqNum1-1;
+  return link->d->icq_UDPSeqNum1-1;
 }
 
 /**************************************************
@@ -601,7 +623,7 @@
   icq_PacketAppend32(p, uin);
   icq_UDPSockWrite(link, p);
   icq_PacketDelete(p);
-  return link->icq_UDPSeqNum1-1;
+  return link->d->icq_UDPSeqNum1-1;
 }
 
 /********************************************************
@@ -613,7 +635,7 @@
   icq_PacketAppend32(p, uin);
   icq_UDPSockWrite(link, p);
   icq_PacketDelete(p);
-  return link->icq_UDPSeqNum1-1;
+  return link->d->icq_UDPSeqNum1-1;
 }
 
 /**************************************************************
@@ -648,7 +670,7 @@
 void icq_RegNewUser(ICQLINK *link, const char *pass) /* V5 */
 {
   char pass8[9];
-  icq_Packet *p = icq_UDPCreateStdSeqPacket(link, UDP_CMD_REG_NEW_USER, link->icq_UDPSeqNum1++);
+  icq_Packet *p = icq_UDPCreateStdSeqPacket(link, UDP_CMD_REG_NEW_USER, link->d->icq_UDPSeqNum1++);
   strncpy(pass8, pass, 8);
   icq_PacketAppendString(p, pass8);
   icq_PacketAppend32(p, 0xA0);
@@ -674,7 +696,7 @@
 /* auth (byte)? */
   icq_UDPSockWrite(link, p);
   icq_PacketDelete(p);
-  return link->icq_UDPSeqNum1-1;
+  return link->d->icq_UDPSeqNum1-1;
 }
 
 WORD icq_UpdateAuthInfo(ICQLINK *link, DWORD auth) /* V5 */
@@ -683,7 +705,7 @@
   icq_PacketAppend32(p, auth); /* NOT auth? */
   icq_UDPSockWrite(link, p);
   icq_PacketDelete(p);
-  return link->icq_UDPSeqNum1-1;
+  return link->d->icq_UDPSeqNum1-1;
 }
 
 WORD icq_UpdateMetaInfoSet(ICQLINK *link, const char *nick, const char *first, const char *last,
@@ -712,7 +734,7 @@
   icq_PacketAppend8(p, emailhide);
   icq_UDPSockWrite(link, p);
   icq_PacketDelete(p);
-  return link->icq_UDPSeqNum2-1;
+  return link->d->icq_UDPSeqNum2-1;
 }
 
 WORD icq_UpdateMetaInfoHomepage(ICQLINK *link, unsigned char age, const char *homepage,
@@ -732,7 +754,7 @@
   icq_PacketAppend8(p, 0xFF /* lang3 */);
   icq_UDPSockWrite(link, p);
   icq_PacketDelete(p);
-  return link->icq_UDPSeqNum2-1;
+  return link->d->icq_UDPSeqNum2-1;
 }
 
 WORD icq_UpdateMetaInfoAbout(ICQLINK *link, const char *about)
@@ -742,7 +764,7 @@
   icq_PacketAppendString(p, about);
   icq_UDPSockWrite(link, p);
   icq_PacketDelete(p);
-  return link->icq_UDPSeqNum2-1;
+  return link->d->icq_UDPSeqNum2-1;
 }
 
 WORD icq_UpdateMetaInfoSecurity(ICQLINK *link, unsigned char reqauth, unsigned char webpresence,
@@ -755,7 +777,7 @@
   icq_PacketAppend8(p, pubip);
   icq_UDPSockWrite(link, p);
   icq_PacketDelete(p);
-  return link->icq_UDPSeqNum2-1;
+  return link->d->icq_UDPSeqNum2-1;
 }
 
 WORD icq_UpdateNewUserInfo(ICQLINK *link, const char *nick, const char *first, const char *last,
@@ -771,7 +793,7 @@
   icq_PacketAppend8(p, 1);
   icq_UDPSockWrite(link, p);
   icq_PacketDelete(p);
-  return link->icq_UDPSeqNum1-1;
+  return link->d->icq_UDPSeqNum1-1;
 }
 
 WORD icq_SendMetaInfoReq(ICQLINK *link, unsigned long uin)
@@ -781,5 +803,5 @@
   icq_PacketAppend32(p, uin);
   icq_UDPSockWrite(link, p);
   icq_PacketDelete(p);
-  return link->icq_UDPSeqNum2-1;
+  return link->d->icq_UDPSeqNum2-1;
 }
--- a/plugins/icq/udphandle.c	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/udphandle.c	Tue Dec 19 10:08:29 2000 +0000
@@ -1,9 +1,12 @@
 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
-$Id: udphandle.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Id: udphandle.c 1319 2000-12-19 10:08:29Z warmenhoven $
 $Log$
-Revision 1.1  2000/11/28 02:22:42  warmenhoven
-icq. whoop de doo
+Revision 1.2  2000/12/19 10:08:29  warmenhoven
+Yay, new icqlib
+
+Revision 1.29  2000/11/02 07:28:30  denis
+Do not ack unhandled protocol version.
 
 Revision 1.28  2000/06/25 17:25:52  denis
 icq_HandleMetaUserInfo() handles all (!) available in original icq2k
@@ -843,10 +846,10 @@
   }
   else
   {
-    icq_FmtLog(link, ICQ_LOG_WARNING, "Unhandled message %04x, Version: %x, "
+    icq_FmtLog(link, ICQ_LOG_WARNING, "Unhandled protocol version! Message %04x, Version: %x, "
                "Sequence: %04x, Size: %d\n", cmd, icq_PacketReadUDPInVer(p),
                seq, p->length);
-    icq_UDPAck(link, seq); /* fake like we know what we're doing */
+/*    icq_UDPAck(link, seq);  DO NOT ACK unhandled protocol version! */
   }
 }
 
--- a/plugins/icq/util.c	Tue Dec 19 08:37:12 2000 +0000
+++ b/plugins/icq/util.c	Tue Dec 19 10:08:29 2000 +0000
@@ -1,9 +1,12 @@
 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
-$Id: util.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Id: util.c 1319 2000-12-19 10:08:29Z warmenhoven $
 $Log$
-Revision 1.1  2000/11/28 02:22:42  warmenhoven
-icq. whoop de doo
+Revision 1.2  2000/12/19 10:08:29  warmenhoven
+Yay, new icqlib
+
+Revision 1.33  2000/08/13 19:26:50  denis
+icq_Genders[] array have been added.
 
 Revision 1.32  2000/07/22 16:49:32  denis
 Trinidad and Tobago country was added.
@@ -356,6 +359,12 @@
   {"Welsh", 67},
 };
 
+icq_ArrayType icq_Genders[] = {
+  {"Not Specified", 0},
+  {"Female", 1},
+  {"Male", 2},
+};
+
 void hex_dump(char *data, long size)
 {
   long i;