changeset 1152:201ec77f3a60

[gaim-migrate @ 1162] icq. whoop de doo committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Tue, 28 Nov 2000 02:22:42 +0000
parents 428372cc1e39
children 3063e6743913
files ChangeLog FIXME configure.in plugins/Makefile.am plugins/icq/.cvsignore plugins/icq/AUTHORS plugins/icq/COPYING plugins/icq/ChangeLog plugins/icq/INSTALL plugins/icq/Makefile.am plugins/icq/Makefile.in plugins/icq/README plugins/icq/VERSION plugins/icq/chatsession.c plugins/icq/chatsession.h plugins/icq/contacts.c plugins/icq/contacts.h plugins/icq/cyrillic.c plugins/icq/filesession.c plugins/icq/filesession.h plugins/icq/gaim_icq.c plugins/icq/icq.h plugins/icq/icqbyteorder.c plugins/icq/icqbyteorder.h plugins/icq/icqlib.c plugins/icq/icqlib.h plugins/icq/icqpacket.c plugins/icq/icqpacket.h plugins/icq/icqtypes.h plugins/icq/list.c plugins/icq/list.h plugins/icq/proxy.c plugins/icq/queue.c plugins/icq/queue.h 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/tcplink.h plugins/icq/udp.c plugins/icq/udp.h plugins/icq/udphandle.c plugins/icq/util.c plugins/icq/util.h src/util.c
diffstat 49 files changed, 11089 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Tue Nov 28 00:53:27 2000 +0000
+++ b/ChangeLog	Tue Nov 28 02:22:42 2000 +0000
@@ -2,7 +2,10 @@
 
 version 0.11.0:
 	* Multiple connections
-	* Protocol plugins (IRC (plugins/irc.c), Yahoo (plugins/yay))
+	* Protocol plugins:
+		IRC (plugins/irc.c)
+		Yahoo (plugins/yay)
+		ICQ (plugins/icq)
 	* Logs now stored to ~/.gaim/logs rather than ~/.gaim/SN/
 	* User configurable sounds
 	* Scroll bar now functions properly in chat room user lists
--- a/FIXME	Tue Nov 28 00:53:27 2000 +0000
+++ b/FIXME	Tue Nov 28 02:22:42 2000 +0000
@@ -1,3 +1,2 @@
 GAIM: Items to be fixed
 ------------------------
-do Buddy Pounces on a per-connection basis
--- a/configure.in	Tue Nov 28 00:53:27 2000 +0000
+++ b/configure.in	Tue Nov 28 02:22:42 2000 +0000
@@ -197,6 +197,7 @@
            sounds/Makefile
 	   plugins/Makefile
 	   plugins/yay/Makefile
+	   plugins/icq/Makefile
            pixmaps/Makefile
            libfaim/Makefile
 	   po/Makefile.in
--- a/plugins/Makefile.am	Tue Nov 28 00:53:27 2000 +0000
+++ b/plugins/Makefile.am	Tue Nov 28 02:22:42 2000 +0000
@@ -5,7 +5,7 @@
 
 if PLUGINS
 
-SUBDIRS = yay
+SUBDIRS = yay icq
 
 plugin_DATA = autorecon.so iconaway.so irc.so notify.so spellchk.so lagmeter.so
 plugindir = $(libdir)/gaim
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/.cvsignore	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,24 @@
+Makefile
+.deps
+.libs
+chatsession.lo
+contacts.lo
+cyrillic.lo
+filesession.lo
+icqbyteorder.lo
+icqlib.lo
+icqpacket.lo
+list.lo
+proxy.lo
+queue.lo
+stdpackets.lo
+tcp.lo
+tcpchathandle.lo
+tcpfilehandle.lo
+tcphandle.lo
+tcplink.lo
+udp.lo
+udphandle.lo
+util.lo
+gaim_icq.lo
+libgaimicq.la
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/AUTHORS	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,9 @@
+Core Developers
+---------------
+Denis V. Dmitrienko <denis@null.net>
+Bill Soudan <soudan@kde.org>
+
+Secondary Developers
+--------------------
+Vadim Zaliva <lord@crocodile.org>
+Nikita I. Makeev <whale@nichego.net> (retired ;)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/COPYING	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,339 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/ChangeLog	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,975 @@
+2000-07-30  Denis V. Dmitrienko  <denis@null.net>
+
+	* ChangeLog, icqlib-0.2.0.lsm, icqlib-1.0.0.lsm, README, TODO,
+	VERSION, Win32.zip:
+	Updated version for 1.0.0 release.
+
+2000-07-25  Denis V. Dmitrienko  <denis@null.net>
+
+	* README: Description was changed a little.
+
+	* icqlib/icq.h.in: Cleanups.
+
+2000-07-23  Bill Soudan  <soudan@kde.org>
+
+	* README: added description
+
+	* icqlib/icq.h.in, icqlib/icqlib.c, icqlib/tcpchathandle.c,
+	icqlib/tcpfilehandle.c: added support for real nickname during
+	TCP transactions like file and chat, instead of using Bill
+	all the time (hmm, where'd I get that from? :)
+
+2000-07-22  Denis V. Dmitrienko  <denis@null.net>
+
+	* AUTHORS, DEVEL, icqlib-0.1.3.lsm, icqlib-0.2.0.lsm, README, TODO:
+	Text files in root directory were changed to reflect latest changes.
+
+2000-07-22  Denis V. Dmitrienko  <denis@null.net>
+
+	* icqlib/util.c: Trinidad and Tobago country was added.
+
+	* icqlib/icq.h.in: Cleanups.
+
+2000-07-21  Denis V. Dmitrienko  <denis@null.net>
+
+	* icqlib/util.c: All languages, possible in original icq were added.
+	Occupation array fixed.
+
+2000-07-20  Denis V. Dmitrienko  <denis@null.net>
+
+	* icqlib/util.c:
+	Occupation table corrected to comply with original ICQ.
+
+2000-07-09  Bill Soudan  <soudan@kde.org>
+
+	* icqlib/list.c: added more trace messages, added list_remove_node
+	call in list_free... fixes list corruption bug introduced
+	during last commit
+
+	* icqlib/queue.c: added more trace messages, reworked packet
+	delete handling: now happens during _icq_UDEQueueItemFree rather
+	than during icq_UDPQueueDelSeq - fixes memory leak
+
+2000-07-09  Bill Soudan  <soudan@kde.org>
+
+	Cleanups, and nasty memory bug fixes.  Hopefully this will
+	correct the strange crashes Denis is having after the icq_Done
+	call!
+
+	The major problem was: icq_TCPLinkDelete and icq_FileSessionDelete
+	were calling list_remove to remove themselves from the global
+	TCPLink and FileSession lists kept in ICQLINK.  But, these
+	functions were being called from a list_delete call also,
+	in icq_TCPDone, so what was happening is the list_nodes were
+	getting free()ed twice!
+
+	This problem was circumvented by removing the list_remove
+	from the *Delete functions, and creating new Close functions
+	that do the list_remove and then call the corresponding 
+	Delete function.
+
+	* icqlib/chatsession.c, icqlib/chatsession.h, icqlib/filesession.c,
+ 	icqlib/tcp.c, icqlib/tcpchathandle.c, icqlib/tcpfilehandle.c,
+	icqlib/tcplink.c, icqlib/tcplink.h, icqlib/udp.c,
+	icqlib/stdpackets.h: adding new *Close functions, use *Close
+	functions instead of *Delete where correct, and misc cleanups
+
+	* icqlib/icq.h.in: removed unnecessary members from ICQLINK
+
+	* icqlib/icqlib.c, icqlib/icqlib.h: removed unnecessary
+	functions
+
+	* icqlib/list.c, icqlib/list.h: recoded list_free function - this
+	was working very incorrectly!  it was only freeing the first
+	node of the list, and then ending.  fixes a memory leak.
+
+	* icqlib/queue.c: use new list_free 
+
+	* icqlib/tcp.c: use Close functions, misc cleanups
+
+2000-07-09  Denis V. Dmitrienko  <denis@null.net>
+
+	* icqlib/icq.h.in: Cleanups.
+
+	* icqlib/icqlib.c:
+	Initial memset() in icq_Init() replaced by callback's clearance.
+
+	* icqlib/udp.c:
+	icq_UpdateNewUserInfo() now returns seq1 instead of seq2 since it
+	isn't META function.
+
+2000-07-07  Denis V. Dmitrienko  <denis@null.net>
+
+	* icqlib/icqpacket.c:
+	"icq_Packet data overflow" log message temporarily commented out.
+
+2000-07-04  Paul Cadach          <paul@odt.east.telecom.kz>
+	* icqlib/utilc:
+	icq_FmtLog() crashed when it receives NULL at link argument.
+
+2000-06-30  Denis V. Dmitrienko  <denis@null.net>
+
+	* icqlib/util.c: Slovak Republic country code fixed.
+
+2000-06-25  Denis V. Dmitrienko  <denis@null.net>
+
+	* icqlib/udphandle.c:
+	icq_HandleMetaUserInfo() handles all (!) available in original icq2k
+	Meta User Info packets along with other useful Meta* packets. (WOW! ;)
+
+	* icqlib/icq.h.in:
+	New callbacks (we really need an event-driven model later):
+	icq_MetaUserFound, icq_MetaUserInfo, icq_MetaUserWork,
+	icq_MetaUserMore, icq_MetaUserAbout, icq_MetaUserInterests,
+	icq_MetaUserAffiliations, icq_MetaUserHomePageCategory
+	New functions-companions for Meta User Info:
+	icq_GetMetaOccupationName(), icq_GetMetaBackgroundName(),
+	icq_GetMetaAffiliationName(), icq_GetMetaLanguageName()
+	New function to request Meta User Info icq_SendMetaInfoReq()
+	COUNTRY_CODE was "generalized" to icq_ArrayType. Note: this is
+	source incompatible change!
+
+	* icqlib/util.c: icq_MetaOccupation[], icq_MetaPastBackgrounds[],
+	icq_MetaAffiliations[] and icq_MetaLanguages[] arrays were added along
+	with icq_GetMetaOccupationName(), icq_GetMetaBackgroundName(),
+	icq_GetMetaAffiliationName() and icq_GetMetaLanguageName() functions
+	to access them.
+
+	* icqlib/udp.h: Some META* defines changed/added.
+	USER_INFO structure which is never been used now removed.
+
+	* icqlib/udp.c: icq_SendMetaInfoReq() was added.
+	All icq_*Meta*() functions now returns sequence number 2 because their
+	replies from the server are synced with it.
+
+	* icqlib/tcphandle.c, icqlib/tcpfilehandle.c, icqlib/eventhandle.c:
+	'\n' was added at the end of log messages.
+
+	* icqlib/queue.c:
+	Some sanity checks were added to icq_UDPQueueDelete() and
+	icq_UDPQueueFree()
+
+	* icqlib/icqpacket.c: icq_PacketUDPDump() tweaked a little.
+
+2000-06-17  Denis V. Dmitrienko  <denis@null.net>
+
+	* icqlib/contacts.c, icqlib/icq.h.in:
+	New parameter was added in icq_ContactSetVis() for setting/resetting
+	'Visible to User' status.
+	Port's type was changed to unsigned short in icq_UserOnline callback.
+
+2000-06-15  Bill Soudan  <soudan@kde.org>
+
+	* icqlib/icqevent.c, icqlib/icqevent.h, icqlib/eventhandle.c,
+	icqlib/eventhandle.h: committed for safekeeping, not used yet.
+	this code will soon replace stdpackets.c and tcphandle.c, as
+	well as reducing code duplication in many other places.  hopefully
+	it can eventually be extended to manage udp events as well, as
+	it's written in pseudo-object-oriented style.
+
+2000-06-14  Bill Soudan  <soudan@kde.org>
+
+	Bugfixes and code cleanups.
+
+	* icqlib/filesession.c, icqlib/filesession.h: added id arg to
+	icq_FindFileSession to allow searches for specific file session
+
+	* icqlib/icq.h.in: removed *Seq functions, renamed chat req functions
+	to be consistent with file req functions, added Cancel and Refuse
+	functions for chat and file reqs
+
+	* icqlib/queue.h: added proto for icq_UDPQueueInterval
+
+	* icqlib/stdpackets.c, icqlib/stdpackets.h: added creation
+	functions for cancel and refuse operations
+
+	* icqlib/tcp.c, icqlib/tcp.h: added Cancel and Refuse functions
+	for chat and file reqs, changed packet sending code to use new
+	icq_TCPLinkSendSeq function to elimitane duplicate code, removed
+	*Seq functions, renamed chat req functions
+
+	* icqlib/tcpfilehandle.c: fixed bug: sending file sessions would
+	freeze if remote side changed speed
+
+	* icqlib/tcplink.c, icqlib/tcplink.h: added icq_TCPLinkSendSeq
+	function
+
+	* icqlib/icqlib.c, icqlib/udp.c: removed *Seq functions
+
+2000-05-21  Denis V. Dmitrienko  <denis@null.net>
+
+	* icqlib/util.c: Bulgaria country code was added. Thanks to
+	"Napalm Death" <napalmbox@hotmail.com>
+
+	* icqlib/cyrillic.c: Applied patch for russian letters IO and io by
+	Vladimir Eltchinov <elik@design.ru>
+
+2000-05-10  Denis V. Dmitrienko  <denis@null.net>
+
+	* icqlib/icq.h.in, icqlib/icqlib.c, icqlib/queue.c,
+	icqlib/queue.h, icqlib/udp.c:
+	UDP outgoing packet queue was implemented.
+
+	* icqlib/udphandle.c, icqlib/proxy.c:
+	icq_Disconnect() now called before icq_Disconnected callback to
+	prevent high CPU usage in kicq's "reconnect on disconnect" code.
+
+	* icqlib/list.c, icqlib/list.h:
+	list_free() was added to free but do not dispose the list.
+	Memory leak with destroying the list was fixed.
+
+2000-05-05  Denis V. Dmitrienko  <denis@null.net>
+
+	* Win32.zip:
+	Automatically generated icq.h repackaged for Win32 portability.
+
+2000-05-04  Bill Soudan  <soudan@kde.org>
+
+	* icqlib/tcp.h: undefined TCP debug trace constants in preparation
+	for release.
+
+	* icqlib/stdpackets.c: warning cleanups.
+
+	* icqlib/icq.h.in: changed FILE_STATUS_* defines, removed
+	many ICQ_NOTIFY_FILE* defines, added new direction member
+	to icq_FileSession, removed unnecessary uin arg from
+	icq_FileSessionSetSpeed.
+
+	* icqlib/tcpchathandle.c, icqlib/tcpfilehandle.c, icqlib/tcphandle.c,
+	icqlib/tcplink.c, icqlib/filesession.c, icqlib/tcp.c:
+	Reworked file transfer notification, small bugfixes,
+	and cleanups.
+
+2000-05-03  Denis V. Dmitrienko  <denis@null.net>
+
+	* icqlib/udp.c: icq_UpdateNewUserInfo() was added.
+	All icq_UpdateMetaInfo*() now return their sequence number.
+
+	* icqlib/chatsession.c, icqlib/filesession.c, icqlib/icq.h.in,
+	icqlib/Makefile.am, icqlib/proxy.c, icqlib/tcpchathandle.c,
+	icqlib/tcpfilehandle.c, icqlib/tcphandle.c, icqlib/tcplink.c,
+	icqlib/udphandle.c, icqlib/util.c, icqlib/callbacks.c:
+	Callbacks have been moved to the ICQLINK structure.
+
+	* icqlib/icqpacket.c, icqlib/icqpacket.h:
+	icq_PacketReadUDPInUIN() was added.
+
+	* icqlib/list.c: Bug with empty contact list was fixed.
+
+	* icqlib/icqlib.c: Unfinished UDP queue was commented out.
+
+2000-04-13  Denis V. Dmitrienko  <denis@null.net>
+
+	* README.Win32, VC5.zip, Win32.zip:
+	icq.h header file which is automatically generated on Unix is packaged
+	in Win32.zip archive along with the Visual C++ 5.0 project file.
+
+2000-04-10  Denis V. Dmitrienko  <denis@null.net>
+
+	* icqlib/chatsession.h, icqlib/filesession.h, icqlib/stdpackets.c,
+	icqlib/tcp.c, icqlib/tcpfilehandle.c, icqlib/tcplink.c:
+	ANSI cleanups.
+
+	* icqlib/filesession.c, icqlib/icqlib.c, icqlib/stdpackets.h,
+	icqlib/tcp.c, icqlib/tcpfilehandle.c, icqlib/tcp.h,
+	icqlib/tcplink.c, icqlib/udp.c, icqlib/udp.h, icqlib/util.c,
+	VC5.zip:
+	Some more Win32 compatibility from Guillaume Rosanis <grs@mail.com>
+
+2000-04-06  Herbert Valerio Riedel  <hvr@gnu.org>
+
+	* icqlib/icq.h.in, icqlib/udp.c (icq_KeepAlive,icq_SendAuthMsg):
+	return sequence number
+
+2000-04-06  Denis V. Dmitrienko  <denis@null.net>
+
+	* icqlib/icq.h.in, icqlib/icqlib.c, icqlib/stdpackets.c, icqlib/tcp.c:
+	icq_*Send*Seq() functions with specified sequence number were added.
+
+	* icqlib/udp.c:
+	So called "Online List problem" bug with Long Contact List was fixed.
+	icq_*Send*Seq() functions with specified sequence number were added.
+
+2000-04-05  Denis V. Dmitrienko  <denis@null.net>
+
+	* README.Win32, VC5.zip, icqlib/icqbyteorder.h, icqlib/icq.h.in,
+	icqlib/icqlib.c, icqlib/icqlib.h, icqlib/icqpacket.c,
+	icqlib/icqtypes.h, icqlib/proxy.c, icqlib/tcp.c,
+	icqlib/tcpchathandle.c, icqlib/tcpfilehandle.c,
+	icqlib/tcphandle.c, icqlib/tcplink.c, icqlib/tcplink.h,
+	icqlib/udp.c, icqlib/util.c, icqlib/util.h:
+	Applied patch from "Guillaume R." <grs@mail.com> for basic Win32
+	compatibility.
+
+2000-03-31  Igor S. Petrenko <nofate@europe.com>
+
+	* icqlib/util.c: remove static variable
+
+2000-03-30  Denis V. Dmitrienko  <denis@null.net>
+
+	* am_edit, configure.in, libtool.m4.in, ltconfig, ltmain.sh,
+	missing, mkinstalldirs, acinclude.m4.in, Makefile.cvs:
+	New autoconf/automake stuff from KDE2.
+
+	* icqlib/queue.c: Fixed FreeBSD warning about obsolete malloc.h
+	header.
+
+2000-02-14  Bill Soudan  <soudan@kde.org>
+
+	Applied patch from Paul Cadach <paul@odt.east.telecom.kz>.
+
+	* icqlib/icq.h.in: added icq_TCPSendChatData_n
+
+	* icqlib/tcp.c: use new icq_ChatRusConv_n function in
+	icq_TCPSendChatData, new icq_TCPSendChatData_n function
+
+	* icqlib/tcplink.c, tcplink.h: new icq_ChatRusConv_n function
+
+2000-02-06  Bill Soudan  <soudan@kde.org>
+
+	* icqlib/tcpchathandle.c: warning cleanups.
+
+2000-02-06  Bill Soudan  <soudan@kde.org>
+
+	Applied patch from Paul Cadach <paul@odt.east.telecom.kz>.  
+	Thanks Paul!
+
+	Paul's change list:
+
+	1) Modified TCP link code to allow non-blocking TCP connects over 
+	SOCKS5 proxy
+	2) Added missed Cyrillic translating for Chat subject, URL subject, 
+	File transfer subject (both directions);    
+	3) Fix a bug in TCPLinkProxyConnect code (remote address was random 
+	due to using local variable instead of plink's remote_address).  
+
+	* icqlib/cyrillic.c, icqlib/icqlib.h: added icq_RusConv_n
+
+	* icqlib/stdpackets.c: slightly modified chat packets
+
+	* icqlib/tcp.c: new code for SOCKS connections, more cyrillic
+	translations
+
+	* icqlib/tcpchathandle.c: new code for special chat functions
+	(background, fonts, etc)
+
+	* icqlib/tcplink.c: implemented non-blocking TCP connects
+	over SOCKS, cyrillic translation for chat
+
+	* icqlib/tcplink.h: new defines for SOCKS5 code
+
+	* icqlib/udphandle.c: changed log message in HandleUserOnline
+	
+2000-02-03  Bill Soudan  <soudan@kde.org>
+
+	* icqlib/icqlib.h: line 33, fixed minor compile bug, changed
+	u_int32_t declaration to unsigned long.  This was causing a 
+	problem compiling on SunOS, as reported by Longwen
+	<longwen@mail.com>
+
+2000-01-20  Bill Soudan  <soudan@kde.org>
+
+	Worked more on file send implementation.  icqlib will now also 
+	handle sending file requests to clients.
+
+	* icqlib/filesession.c, filesession.h, icq.h.in, stdpackets.c
+	stdpackets.h, tcp.c, tcpfilehandle.c, tcphandle.c:
+	first implementation of sending file requests
+
+	* icqlib/tcplink.c: fixed bug in icq_TCPLinkConnect that caused
+	file/chat connection attempts to go to the wrong port
+
+2000-01-16  Bill Soudan  <soudan@kde.org>
+
+	Exported icq_FileSession structure to library clients;
+	fixed a serious list bug.  Oops. :)
+
+	* icqlib/filesession.c, filesession.h: added new public functions,
+	icq_FileSessionSetSpeed, icq_FileSessionClose,
+	icq_FileSessionSetWorkingDir, moved icq_FileSession interface to
+	icq.h.in
+	
+	* icqlib/icq.h.in: added definition for icq_FileSession and new
+	public functions
+
+	* icqlib/list.c: fixed serious bug in list_remove
+
+	* icqlib/tcp.c: renamed icq_TCPAcceptFileReq to
+	icq_AcceptFileRequest, moved file request functions to new
+	file session code
+
+	* icqlib/tcpfilehandle.c: added code so icq_FileSessions now
+	keep track of the tcplink to which they are attached
+
+	* icqlib/tcplink.h: removed list_node from icq_TCPLink
+
+2000-01-15  Bill Soudan  <soudan@kde.org>
+
+	Reworked list routines so list_node's don't need to be
+	inside item structures.  Note this made the strlist code
+	unnecessary - strlist code was replaced with generic list
+	commands.
+
+	* icqlib/Makefile.am: strlist.c, strlist.h removed
+
+	* chatsession.c, chatsession.h, contacts.c, contacts.h,
+	filesession.c, filesession.h, icqlib.c, icqpacket.c, icqpacket.h,
+	list.c, list.h, queue.c, queue.h, tcp.c, tcplink.c, tcplink.h,
+	udphandle.c: reworked list code, removed strlist code
+
+	* strlist.c, strlist.h: removed
+
+1999-12-27  Bill Soudan  <soudan@kde.org>
+
+	* icqlib/icq.h.in: added proto for icq_TCPFileSetSpeed
+
+	* icqlib/icqlib.c: cleanups
+
+	* icqlib/tcp.c: fixed bug in icq_TCPAcceptFileReq, added
+	icq_TCPFileSetSpeed
+
+	* icqlib/tcplink.c: fixed bug in icq_TCPOnDataReceived,
+	removed flags variable ;) 
+
+1999-12-27  Denis V. Dmitrienko  <denis@null.net>
+
+	* icqlib/udphandle.c, icqlib/udp.h, icqlib/udp.c, icqlib/icq.h.in:
+	icq_UpdateMetaInfoSecurity() added for setting "My authorization is
+	required", "Web Aware" and "IP Publishing".
+
+	* icqlib/tcplink.c: Unused "flags" variable commented out.
+
+1999-12-20  Bill Soudan  <soudan@kde.org>
+
+	Worked more on file transfer.  icqlib will now write received
+	files to disk, and handles all transfer details accordingly
+	after icq_TCPAcceptFileReq is called.  Note currently
+	files are always saved in current directory.  Receiving a
+	single file is working 100% as best I can tell - receiving
+	multiple files hasn't been tested well but should work.
+
+	Also reworked icq_TCPLinkOnDataRecevied to handle quick, large
+	streams of data (processing 1 packet every main loop call
+	just didn't cut it :), and at the same time fixed a bug where
+	received packets would not get processed if the remote end
+	closed the connection immediately after sending one.  This had
+	the result that the tcp sockets stay in non-blocking mode
+	for their entire life, instead of just during connect
+	as before.
+
+	Resume is currently off-by-one I think.  Don't rely on it.
+
+	* icqlib/filesession.[ch]: added file open/close logic, changed
+	icq_FileSession struct a bit
+
+	* icqlib/icq.h.in: removed unnecessary icq_TCPSendFile??Packet
+	functions, user programs do not use these
+
+	* icqlib/tcp.[ch]: moved _process_packet logic into tcplink::
+	icq_TCPLinkProcessReceived, removed unnecessary
+	icq_TCPSendFile??Packet functions
+
+	* icqlib/tcpfilehandle.c: added more file transfer logic to
+	write file to disk
+
+	* icqlib/tcplink.c: added icq_TCPLinkProcessReceived to
+	support processing receive queue before delete (packets used
+	to get dropped in this instance, oops), reworked 
+	icq_TCPLinkOnDataReceived to handle quick, large streams
+	of data, changed icq_TCPLinkOnConnect and *Accept to
+        make all sockets non-blocking.
+
+1999-12-13  Bill Soudan  <soudan@kde.org>
+
+	Implemeted SF task #10224, use real_ip when our IP and remote
+	IP are same, and task #10203, connect timeout for tcp requests.
+
+	Fixed bug #100312, double freeing of list item.
+
+	NOTE: masq hack in udphandle.c::icq_HandleUserOnline is now gone!
+        Updated connect logic _should_ automatically do that for us now.
+
+	* icqlib/contacts.h: added remote_real_ip member to icq_ContactItem 
+	struct 
+
+	* icqlib/tcp.c: fixed double delete bug in _handle_ready_sockets,
+	added code to implement connect timeout
+	
+	* icqlib/tcplink.c: icq_TCPLinkConnect now uses real_ip when
+	our IP is same as remote IP to make connection, added
+	code to implement connect timeout
+
+	* icqlib/tcplink.h: added TCP_LINK_CONNECT_TIMEOUT constant,
+	added connect_time to icq_TCPLink struct
+
+	* icqlib/udphandle.c: removed old real_ip->ip masq hack,
+        added store to remote_real_ip in icq_ContactItem 
+
+1999-12-12  Denis V. Dmitrienko  <denis@null.net>
+
+	* icqlib/udphandle.c: Authorization Request packet handling fixed.
+
+	* Makefile.am: DEVEL file included
+
+1999-12-02  Bill Soudan  <soudan@kde.org>
+
+	commited missing filesession.c and filesession.h files.  Sorry
+	'bout that :)
+
+1999-11-30  Bill Soudan  <soudan@kde.org>
+
+	More file xfer support added.  icqlib tcp will now 'go through the
+	motions' for receiving a file.  file data is not written to 
+	disk, yet.
+	
+	* icqlib/Makefile.am: added filesession.[ch]
+
+	* icqlib/icq.h.in: new notify constant (ICQ_NOTIFY_FILE),
+	new icq_FileSessions member in icqlink struct, new AcceptFileReq
+	prototype
+
+	* icqlib/icqpacket.h: ICQ_PACKET_DATA_SIZE increased to 4096
+	to support file transfer packets
+
+	* icqlib/tcp.c: added file session logic
+
+	* icqlib/tcpfilehandle.c: added icq_HandleFileHello
+
+	* icqlib/tcphandle.c: more file xfer logic added
+
+	* icqlib/tcplink.c, tcplink.h: buffer overflow check added,
+	tcplinks will now close if buffer overflows.  increased
+	icq_TCPLinkBufferSize to 4096 to support file transfer packets
+
+1999-11-29  Denis V. Dmitrienko  <denis@null.net>
+
+	* icqlib/udphandle.c: icq_DoMsg() redone using string lists.
+
+	* icqlib/strlist.c, icqlib/strlist.h:
+	General interface for string lists added.
+
+	* icqlib/tcplink.c: Absence of socklen_t type fixed.
+
+	* icqlib/icq.h.in, icqlib/callbacks.c:
+	icq_RecvMailExpress callback added.
+
+	* icqlib/Makefile.am: strlist.[ch] added.
+
+1999-10-14  Denis V. Dmitrienko  <denis@null.net>
+
+	* icq.h.in, udp.c: icq_UpdateMetaInfo* functions added.
+
+1999-10-07  Denis V. Dmitrienko  <denis@null.net>
+
+	* icq.h.in, tcp.h: Internal/external functions declarations
+	unified a little.
+
+	* kicq/Makefile.am, proxy.c, udp.c: proxy.h file removed.
+
+1999-10-06  Denis V. Dmitrienko  <denis@null.net>
+
+	* DEVEL: Added the "developers' hint guide". Please read it
+	carefully.
+
+1999-09-29  Bill Soudan  <soudan@kde.org>
+
+        Check out my spiffy new email address! :)
+
+        Renamed all tcp_link* functions to icq_TCPLink*.
+
+        Forgot to note: fixed memory leak in tcp.c (tcp packets were not
+        being deleted after use... oops :)
+
+	* chatsession.c, tcpchathandle.c, tcpfilehandle.c, tcphandle.c,
+        chatsession.h: reworked chat/file handling.  fixed chat. (it's
+        been broke since I put non-blocking connects in)
+
+        * Makefile.am: added new files
+
+        * icq.h.in: changed some notification values, added support for
+        chat sessions to icqlink
+
+        * icqlib.h, udp.h: moved a bunch of udp-only defines to udp.h
+
+	* icqpacket.c, list.c: cleanups
+
+        * tcp.c: cleanups, moved connect logic from _handle_ready_sockets
+        to icq_TCPLinkOnConnect, tcp_link->icq_TCPLink
+
+        * tcplink.c, tcplink.h: renamed tcp_link* to icq_TCPLink*.  many
+        cleanups, added icq_TCPLinkOnConnect
+
+        * stdpackets.c, stdpackets.h, tcp.h: tcp_link*->icq_TCPLink*
+
+	* udp.c: tcp port wasn't being sent properly in login packet
+
+1999-09-29  Denis V. Dmitrienko  <denis@null.net>
+
+	Show must go on! Hopefully fixed CVS problems.
+
+	* icqlib.c: Host/network/icq byteorder systemized.
+	icq_Init() cleaned up.
+
+	* acconfig.h, configure.in, icqlib.m4.in,
+	icqlib/icqbyteorder.[ch]: More optimized byteswap stuff.
+
+	* icqlib.h: LOGIN_*_TCP defines added.
+
+	* icqpacket.[ch]: icq_PacketAppend16n() added for network-ordered
+	word appending.
+
+	* queue.[ch]: ICQLINK compatibility added.
+
+	* stdpackets.c: Host/network byteorder cleanups.
+
+	* tcplink.c: TCP code SOCKS-ification. Not finished.
+
+	* udp.c: Webaware functions enabled without success even with
+	UDP v5 - need more investigations.
+
+	* udphandle.c: MailExpress message handler started.
+
+1999-07-18  Bill Soudan          <wes0472@rit.edu>
+
+	fixed tcp problems, changed icq_ContactItem structure to use
+	list.c and moved to contacts.c, removed old byte swap macros
+        in favor of new functions in icqbyteorder.c, and added better
+        log messages
+
+	* Makefile.am: added contacts.c, contacts.h
+
+	* contacts.c, contacts.h: added
+
+	* icq.h.in: moved icq_ContactItem struct to contacts.h,
+        removed old *Sok members, renamed icq_Cont* functions
+
+	* icqlib.c, icqlib.h: changed to use new byte-order functions &
+	contact list functions
+
+	* icqpacket.c: changed to use new byte-order functions
+
+	* tcp.c: added better log messages
+
+	* tcplink.c: fixed fail notification bug introduced during ICQLINK
+        changes, changed to use new byte-order functions & contact list
+        functions, added better log messages 
+
+	* udp.c: changed to use new byte-order functions &
+        contact list functions
+
+	* udphandle.c: fixed tcp port bug in icq_HandleUserOnline, changed
+        to use new byte-order & contact list functions
+
+	* util.c, util.h: removed old byte order and contact list
+        functions
+
+1999-07-16  Denis V. Dmitrienko  <denis@null.net>
+
+	Version changed to 0.2.0
+
+	* udp.c, udp.h, udphandle.c: ICQ UDP v5 implemented.
+ 	Encription for ICQ UDP v5 implemented.
+ 	icq_Packet* unified interface for UDP packets implemented.
+	Multipacket support of ICQ UDP v5 added.
+
+	* util.[ch]: Status support changed to support early unsupported
+	combined (ORed) statuses.
+
+	* Makefile.am, icqlib/Makefile.am: Remove automatically generated
+	files by "make maintainer-clean"
+
+1999-07-02  Vadim Zaliva  <lord@crocodile.org>
+
+	* icqlib/udphandle.c (icq_HandleUserOnline): using icqtohl macros
+	to convert parameters of callback (IP addresses, port #) to host
+	order.
+
+	* icqlib/icqbyteorder.h: added (per Bill suggestion) defenitions
+	of icqtohs, icqtons, ntociqs, htociqs macros.
+
+	* icqlib/tcppacket.c: some system header files included to avoid
+	compilation warnings.
+
+	* icqlib/tcplink.c: some system header files included to avoid
+	compilation warnings.
+
+	* icqlib/tcp.h: icq_TCPProcessFilePacket prototype added to avoid
+	compilation warnings.
+
+	* icqlib/tcp.c: add includes to avoid compilation warning for
+	getsockopt() and some other functions.
+
+	* configure.in: add detection of headers used on Solaris, Linux,
+	FreeBSD to detect edianness.
+
+	* icqlib/icqbyteorder.h: defenition of icqtohl, icqtonl, ntociql,
+	htociql macros.
+
+1999-07-02  Bill Soudan          <wes0472@rit.edu>
+
+	icq_SendMessage and icq_SendURL now accept a 3 choice thruSrv arg:
+        ICQ_SEND_THRUSERVER, ICQ_SEND_DIRECT, or ICQ_SEND_BESTWAY.
+        added support to icq_ContactItem structure and udphandle.c.
+
+	* icq.h: added new ICQ_SEND_* constants
+
+	* icqlib.c: added new code to support thruSrv arg to SendMessage
+	and SendURL
+
+	* util.h: added tcp_flag member to icq_ContactItem struct
+
+	* udphandle.c: added code to HandleUserOnline to update tcp_flag
+
+1999-06-30  Bill Soudan          <wes0472@rit.edu>
+
+	implemented non-blocking connects, including checking for failed
+        connects.  failed sends/other networking calls still to do.
+
+	* icq.h: renamed ICQ_NOTIFY_CONNECTFAILED to ICQ_NOTIFY_FAILED
+
+        * list.h, list.c: changed list_traverse to use va_list
+
+	* tcpprocess.c: cleanups
+
+	* tcp.c, tcplink.c, tcplink.h: implemented non-blocking connects
+c
+1999-05-03  Bill Soudan          <wes0472@rit.edu>
+
+	* tcplink.c: removed exit calls
+
+        * callbacks.c, icq.h, tcp.c, tcp.h, tcppackets.c, tcppackets.h,
+        tcpprocess.c: initial file xfer support added- untested
+
+1999-04-29  Denis V. Dmitrienko  <denis@null.net>
+
+	* icqlib.h, udp.c, udp.h, udphandle.c: Unsuccessful attempt to
+	implement web presence (webaware) feature - doesn't seems to work
+	in ICQ v2.
+
+	* list.c, tcp.c, tcplink.c, tcpprocess.c: Cleanups, warning
+	removed
+
+	* Makefile.in, acinclude.m4, aclocal.m4, config.h.in, configure,
+	stamp-h.in, icqlib/Makefile.in: Removed automake/autoconf
+	generated tools from CVS - "make -f Makefile.cvs" to generate them 
+	after checkout.
+
+1999-04-17  Bill Soudan          <wes0472@rit.edu>
+
+	reworked tcp system significantly- tcp links are now kept as a
+        seperate list instead of in icq_ContactItem.  chat requests can now be
+        both sent and received successfully.
+
+	* util.c, util.h, udphandle.c: removed *_link entries from
+        icq_ContactItem, including cleaup/init code
+
+	* icqlib.c, icq.h: modified Send* functions to return DWORD
+        instead of WORD
+
+	* tcp.c: _major_ restructuring.  all tcp sockets (including 
+        listening sockets) are kept in global linked list, icq_TCPLinks.
+        accept and listen functions moved to tcplink.c.  changed return
+        values of Send* functions to DWORD.
+
+	* tcp.h: changed return values of Send* functions to DWORD.
+
+	* tcplink.c, tcplink.h: fixed bug in tcp_link_on_data_received,
+        multiple packets that come in on one recv call are now handled
+        correctly.  added tcp_link_accept and tcp_link_listen.  started
+        using mode and type structure entries.  added icq_TCPLinks list
+        and find_tcp_link function.  changed received_queue and send_queue
+        to lists.
+
+	* tcppacket.c, tcppacket.h: added tcp_packet_node_delete function
+        and changed structure to include list_node for new list routines.
+
+	* tcppackets.c, tcppackets.h: added new functions to create
+        chat packets. removed unnecessary code.  added new function to
+        create URL ack packet.
+
+	* tcpprocess.c: reworked code to use tcp_links instead of
+        icq_ContactItem entries.  modified ProcessChatPacket to negotiate
+        both sending and receiving chat requests properly.
+
+	* list.c, list.h: new list functions- replaces packetqueue
+        and handles new list of tcp_links
+
+	* packetqueue.c, packetqueue.h: removed, list.c now used for
+	queues
+
+	* Makefile.am: removed packetqueue.c, added list.c
+
+1999-04-14  Denis V. Dmitrienko  <denis@null.net>
+
+	* tcpprocess.c: icq_ContactItem parameter added to function
+	icq_TCPOnMessageReceived(). Segfault fixed on spoofed messages.
+
+	* icqlib.c, proxy.c, packetqueue.c, icqlib.h, tcp.c, tcp.h,
+	tcplink.c, udp.c, udp.h, udphandle.c, util.c, util.h, tcppacket.c,
+	tcppackets.c, tcpprocess.c, tcppackets.h: Cleanups for "strict"
+	compiling (-ansi -pedantic)
+
+	* icqlib.c, proxy.c, udp.c, udphandle.c, cyrillic.c: Switched from
+	icq_Log callback to icq_FmtLog function.
+
+	* tcp.h: Some declarations added
+
+	* tcp.c: Parameter port added to icq_TCPCreateListeningSocket()
+	function.
+
+	* icq.h: Added icq_FmtLog()
+
+	* configure: Added AC_CHECK_COMPILERS to allow --enable-debug and
+	--enable-strict configure options.
+
+1999-04-05  Bill Soudan          <wes0472@rit.edu>
+
+        icqlib will now create and listen on the chat socket when
+        necessary, and will perform negotiation for _receiving_ remote
+        chat requests only.          
+
+	* callbacks.c icq.h tcp.c tcp.h tcplink.c tcplink.h tcppacket.c       
+        tcppackets.c tcppackets.h tcpprocess.c udphandle.c util.c
+        util.h: added initial chat support
+
+1999-04-05  Denis V. Dmitrienko  <denis@null.net>
+
+	* icqlib.c: Send messages and URLs to 'not in list' users fixed.
+
+1999-03-30  Bill Soudan           <wes0472@rit.edu>
+
+        tcp messages and urls completely functional!
+        unsuccessful connects not handled yet, however, plus connect
+        is currently blocking (yuck)
+
+	* util.c: cleaned up old TCPLog function
+	* udphandle.c: added tcpflag handling to UserOnline
+	* icq.h: added icq_TCPSendURL and modified icq_UserOnline to
+          handle tcpflag
+	* icqlib.c: added tcp support to SendURL
+	* icqlib.h: modified LOGIN_X2_DEF to 0x04 instead of 0x06- we're
+          ready to accept tcp packets now!  removed duplicate LOGIN_X*
+          definitions
+	* packetqueue.c tcp.c tcp.h tcplink.c tcppacket.c tcppackets.c
+	  tcppackets.h tcpprocess.c: wrapped up many tcp details-  code
+	  now handles incoming and outgoing tcp messages and urls!
+
+1999-03-30  Vadim Zaliva  <lorda@crocodile.org>
+
+	* icqlib/util.c (icq_GetCountryName): function prototype now takes
+	'unsigned short' as country code.
+	Country codes list now prorerly sorted, thus no need to sort it
+	using qsort.
+
+1999-03-29  Vadim Zaliva  <lord@crocodile.org>
+
+	* icqlib/util.c (icq_ConvertStatus2Str): this function now accepts
+	ulong as sttatus argument, since we use unsigned long for status
+	everywhere.
+	(icq_TCPXlateStatus): This function now use unsigned long as
+	'udp_status' parameter type.
+	(icq_GetCountryName): Optimized country code search.
+	(icq_TCPXlateStatus): cleanup.
+
+	* icqlib/icq.h: Change state constants to long.
+
+1999-03-27  Bill Soudan          <wes0472@rit.edu>
+
+        preliminary tcp support added and functional!
+        tcp messages will send to and from remote client when kicq
+        initiates the connection- remote clients will not try a tcp
+        connection to kicq yet
+
+	* icq.h: added extern TCP function prototypes
+        * icqlib.c: added TCP support to icq_SendMessage
+	* packetqueue.c: cleaned up, fixed bugs, finished packet_queue_dump
+	* tcp.c: added icq_TCPSendMessage and socket close/process logic
+	* tcplink.c: fixed tcp_link_connect so it really connects to
+          remote client instead of always to my local test computer O:)
+	* tcppacket.c: added code to handle null string in 
+          tcp_packet_append_string
+	* tcppackets.c,h: CreateStdPacket actually puts IP and port info
+	  in now, added CreateStdAck and CreateMessageAck
+	* udphandle.c: fixed bug in HandleUserOnline (remote_ip and
+          remote_real_ip were not evaluating correctly), added hack
+          so I can test using local network, fixed function names
+          so icqlib compiles
+	* tcpprocess.c: added code to handle received messages,
+          finished process ack function
+	* util.c: removed static from Country_Codes so regwin.cpp
+          from kicq can use it
+
+1999-03-26  Bill Soudan          <wes0472@rit.edu>
+
+	* tcp.c, tcp.h: finished select logic
+	* tcplink.c: fixed C++ comments, cleaned up
+	* tcpprocess.c: added icq_TCPProcessHello
+	* packetqueue.c: moved packet_queue_find_queue from tcp.c
+	* util.c: rewrote icq_TCPLog
+
+1999-03-25  Bill Soudan          <wes0472@rit.edu>
+
+	* tcplink.c, tcplink.h: added
+	* Makefile.am: added tcplink.c
+	* icqlib.c: added #include "util.h"
+	* tcp.c, tcp.h: moved many functions into tcplink.c
+	* tcpprocess.c: changed types to standard
+	* udphandle.c: modified HandleUserOnline & Offline for new message_link
+	* util.c: ContItem functions modified for message_link
+	* util.h: message_link added to ContactItem struct, moved types to
+          seperate file
+	* icqtypes.h: added
+	* tcppacket.h: cleaned up
+
+1999-03-24  Denis V. Dmitrienko  <denis@null.net>
+
+	* Makefile.am, Makefile.in, callbacks.c, cyrillic.c, icq.h,
+	icqlib.c, icqlib.h, packetqueue.c, packetqueue.h, proxy.c,
+	proxy.h, tcp.c, tcp.h, tcppacket.c, tcppacket.h, tcppackets.c,
+	tcppackets.h, tcpprocess.c, udp.c, udp.h, udphandle.c, util.c,
+	util.h:
+ 	Underscored files with TCP stuff renamed.
+	TCP stuff cleaned up
+	Function names changed to corresponding names.
+	icqlib.c splitted to many small files by subject.
+	C++ comments changed to ANSI C comments.
+
+	* Makefile.cvs, Makefile.in, acconfig.h, acinclude.m4,
+	acinclude.m4.in, aclocal.m4, config.guess, config.h.in,
+	config.sub, configure, configure.in, install-sh, libtool.m4.in,
+	ltconfig, ltmain.sh, mkinstalldirs, stamp-h.in: Updated
+	autoconf/automake/libtool configuration tools
+
+1999-03-22  Bill Soudan          <wes0472@rit.edu>
+
+	* Makefile.am: added new files
+
+	* icqlib.h, icqlib.c: added additional struct entries in
+          icq_ContactItem for tcp code, added code in
+	  icq_HandleUserOnline and icq_HandleUserOffline for setup/cleanup
+
+	* added many files for tcp implementation:
+	  icq_tcp.c icq_tcp.h icq_tcp_packets.c icq_tcp_packets.h
+          icq_tcp_process.c packet_queue.c packet_queue.h
+          tcp_packet.c tcp_packet.h util.c
+
+1999-03-05  Denis V. Dmitrienko  <denis@null.net>
+
+	* icqlib.h, icqlib.c, icq.h: Some cosmetic changes...
+
+Version 0.1.3 (08 Dec 1998)
+  SOCKS5 proxy support.
+  icq_RecvMessage now returns sending message time not receiving.
+  Visible list support changed.
+  Handle icq99a statuses.
+
+Version 0.1.2 (05 Oct 1998)
+  Search by UIN added.
+  SunOS port (Thanks to Joe Avila <joe@avilate.com>).
+
+Version 0.1.1 (21 Sep 1998)
+  Renamed from libicq to icqlib - there is another libicq on the net.
+  Little changes to allow UI call select() itself.
+
+Version 0.1.0 (18 Sep 1998)
+  Initial public version.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/INSTALL	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,167 @@
+Basic Installation
+==================
+
+   These are generic installation instructions.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+   The file `configure.in' is used to create `configure' by a program
+called `autoconf'.  You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.  If you're
+     using `csh' on an old version of System V, you might need to type
+     `sh ./configure' instead to prevent `csh' from trying to execute
+     `configure' itself.
+
+     Running `configure' takes a while.  While running, it prints some
+     messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Type `make install' to install the programs and any data files and
+     documentation.
+
+  4. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  You can give `configure'
+initial values for variables by setting them in the environment.  Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+     CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+     env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory.  After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+   By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc.  You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on.  Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+     CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+   If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+     Use and save the results of the tests in FILE instead of
+     `./config.cache'.  Set FILE to `/dev/null' to disable caching, for
+     debugging `configure'.
+
+`--help'
+     Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`--version'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/Makefile.am	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,48 @@
+CFLAGS += -I\$(top_srcdir)/src
+LIBS = $(GTK_LIBS)
+
+EXTRA_DIST =	AUTHORS \
+		COPYING \
+		ChangeLog \
+		INSTALL \
+		README \
+		VERSION
+
+pkgdir = $(libdir)/gaim
+pkg_LTLIBRARIES = libgaimicq.la
+
+libgaimicq_la_SOURCES =	chatsession.c \
+			chatsession.h \
+			contacts.c \
+			contacts.h \
+			cyrillic.c \
+			filesession.c \
+			filesession.h \
+			icq.h \
+			icqbyteorder.c \
+			icqbyteorder.h \
+			icqlib.c \
+			icqlib.h \
+			icqpacket.c \
+			icqpacket.h \
+			icqtypes.h \
+			list.c \
+			list.h \
+			proxy.c \
+			queue.c \
+			queue.h \
+			stdpackets.c \
+			stdpackets.h \
+			tcp.c \
+			tcp.h \
+			tcpchathandle.c \
+			tcpfilehandle.c \
+			tcphandle.c \
+			tcplink.c \
+			tcplink.h \
+			udp.c \
+			udp.h \
+			udphandle.c \
+			util.c \
+			util.h \
+			gaim_icq.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/Makefile.in	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,405 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+AS = @AS@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+DATADIRNAME = @DATADIRNAME@
+DLLTOOL = @DLLTOOL@
+ESD_CFLAGS = @ESD_CFLAGS@
+ESD_CONFIG = @ESD_CONFIG@
+ESD_LIBS = @ESD_LIBS@
+GENCAT = @GENCAT@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_CONFIG = @GLIB_CONFIG@
+GLIB_LIBS = @GLIB_LIBS@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GNOMEGNORBA_LIBS = @GNOMEGNORBA_LIBS@
+GNOMEUI_LIBS = @GNOMEUI_LIBS@
+GNOME_APPLETS_LIBS = @GNOME_APPLETS_LIBS@
+GNOME_CAPPLET_LIBS = @GNOME_CAPPLET_LIBS@
+GNOME_CONFIG = @GNOME_CONFIG@
+GNOME_INCLUDEDIR = @GNOME_INCLUDEDIR@
+GNOME_LIBDIR = @GNOME_LIBDIR@
+GNOME_LIBS = @GNOME_LIBS@
+GNORBA_CFLAGS = @GNORBA_CFLAGS@
+GNORBA_LIBS = @GNORBA_LIBS@
+GTKXMHTML_LIBS = @GTKXMHTML_LIBS@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_CONFIG = @GTK_CONFIG@
+GTK_LIBS = @GTK_LIBS@
+GT_NO = @GT_NO@
+GT_YES = @GT_YES@
+INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@
+INSTOBJEXT = @INSTOBJEXT@
+INTLDEPS = @INTLDEPS@
+INTLLIBS = @INTLLIBS@
+INTLOBJS = @INTLOBJS@
+LDADD = @LDADD@
+LIBOBJS = @LIBOBJS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+MAKEINFO = @MAKEINFO@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+OBJDUMP = @OBJDUMP@
+ORBIT_CFLAGS = @ORBIT_CFLAGS@
+ORBIT_CONFIG = @ORBIT_CONFIG@
+ORBIT_IDL = @ORBIT_IDL@
+ORBIT_LIBS = @ORBIT_LIBS@
+PACKAGE = @PACKAGE@
+POFILES = @POFILES@
+POSUB = @POSUB@
+PTHREAD_LIB = @PTHREAD_LIB@
+RANLIB = @RANLIB@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+XPM_LIBS = @XPM_LIBS@
+ZVT_LIBS = @ZVT_LIBS@
+gaimpath = @gaimpath@
+gnomepath = @gnomepath@
+l = @l@
+perlpath = @perlpath@
+sedpath = @sedpath@
+
+CFLAGS = @CFLAGS@ -I\$(top_srcdir)/src
+LIBS = $(GTK_LIBS)
+
+EXTRA_DIST = AUTHORS 		COPYING 		ChangeLog 		INSTALL 		README 		VERSION
+
+
+pkgdir = $(libdir)/gaim
+pkg_LTLIBRARIES = libgaimicq.la
+
+libgaimicq_la_SOURCES = chatsession.c 			chatsession.h 			contacts.c 			contacts.h 			cyrillic.c 			filesession.c 			filesession.h 			icq.h 			icqbyteorder.c 			icqbyteorder.h 			icqlib.c 			icqlib.h 			icqpacket.c 			icqpacket.h 			icqtypes.h 			list.c 			list.h 			proxy.c 			queue.c 			queue.h 			stdpackets.c 			stdpackets.h 			tcp.c 			tcp.h 			tcpchathandle.c 			tcpfilehandle.c 			tcphandle.c 			tcplink.c 			tcplink.h 			udp.c 			udp.h 			udphandle.c 			util.c 			util.h 			gaim_icq.c
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../config.h
+CONFIG_CLEAN_FILES = 
+LTLIBRARIES =  $(pkg_LTLIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../..
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+libgaimicq_la_LDFLAGS = 
+libgaimicq_la_LIBADD = 
+libgaimicq_la_OBJECTS =  chatsession.lo contacts.lo cyrillic.lo \
+filesession.lo icqbyteorder.lo icqlib.lo icqpacket.lo list.lo proxy.lo \
+queue.lo stdpackets.lo tcp.lo tcpchathandle.lo tcpfilehandle.lo \
+tcphandle.lo tcplink.lo udp.lo udphandle.lo util.lo gaim_icq.lo
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON =  README AUTHORS COPYING ChangeLog INSTALL Makefile.am \
+Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+DEP_FILES =  .deps/chatsession.P .deps/contacts.P .deps/cyrillic.P \
+.deps/filesession.P .deps/gaim_icq.P .deps/icqbyteorder.P \
+.deps/icqlib.P .deps/icqpacket.P .deps/list.P .deps/proxy.P \
+.deps/queue.P .deps/stdpackets.P .deps/tcp.P .deps/tcpchathandle.P \
+.deps/tcpfilehandle.P .deps/tcphandle.P .deps/tcplink.P .deps/udp.P \
+.deps/udphandle.P .deps/util.P
+SOURCES = $(libgaimicq_la_SOURCES)
+OBJECTS = $(libgaimicq_la_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .lo .o .s
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+	cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/icq/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+	cd $(top_builddir) \
+	  && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-pkgLTLIBRARIES:
+
+clean-pkgLTLIBRARIES:
+	-test -z "$(pkg_LTLIBRARIES)" || rm -f $(pkg_LTLIBRARIES)
+
+distclean-pkgLTLIBRARIES:
+
+maintainer-clean-pkgLTLIBRARIES:
+
+install-pkgLTLIBRARIES: $(pkg_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	$(mkinstalldirs) $(DESTDIR)$(pkgdir)
+	@list='$(pkg_LTLIBRARIES)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    echo "$(LIBTOOL)  --mode=install $(INSTALL) $$p $(DESTDIR)$(pkgdir)/$$p"; \
+	    $(LIBTOOL)  --mode=install $(INSTALL) $$p $(DESTDIR)$(pkgdir)/$$p; \
+	  else :; fi; \
+	done
+
+uninstall-pkgLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	list='$(pkg_LTLIBRARIES)'; for p in $$list; do \
+	  $(LIBTOOL)  --mode=uninstall rm -f $(DESTDIR)$(pkgdir)/$$p; \
+	done
+
+.s.o:
+	$(COMPILE) -c $<
+
+.S.o:
+	$(COMPILE) -c $<
+
+mostlyclean-compile:
+	-rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+	-rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.s.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+	$(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+libgaimicq.la: $(libgaimicq_la_OBJECTS) $(libgaimicq_la_DEPENDENCIES)
+	$(LINK) -rpath $(pkgdir) $(libgaimicq_la_LDFLAGS) $(libgaimicq_la_OBJECTS) $(libgaimicq_la_LIBADD) $(LIBS)
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	here=`pwd` && cd $(srcdir) \
+	  && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)'; \
+	unique=`for i in $$list; do echo $$i; done | \
+	  awk '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+	-rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = plugins/icq
+
+distdir: $(DISTFILES)
+	here=`cd $(top_builddir) && pwd`; \
+	top_distdir=`cd $(top_distdir) && pwd`; \
+	distdir=`cd $(distdir) && pwd`; \
+	cd $(top_srcdir) \
+	  && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu plugins/icq/Makefile
+	@for file in $(DISTFILES); do \
+	  d=$(srcdir); \
+	  if test -d $$d/$$file; then \
+	    cp -pr $$d/$$file $(distdir)/$$file; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+	    || cp -p $$d/$$file $(distdir)/$$file || :; \
+	  fi; \
+	done
+
+DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
+
+-include $(DEP_FILES)
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+	-rm -rf .deps
+
+maintainer-clean-depend:
+
+%.o: %.c
+	@echo '$(COMPILE) -c $<'; \
+	$(COMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+	@-cp .deps/$(*F).pp .deps/$(*F).P; \
+	tr ' ' '\012' < .deps/$(*F).pp \
+	  | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+	    >> .deps/$(*F).P; \
+	rm .deps/$(*F).pp
+
+%.lo: %.c
+	@echo '$(LTCOMPILE) -c $<'; \
+	$(LTCOMPILE) -Wp,-MD,.deps/$(*F).pp -c $<
+	@-sed -e 's/^\([^:]*\)\.o[ 	]*:/\1.lo \1.o :/' \
+	  < .deps/$(*F).pp > .deps/$(*F).P; \
+	tr ' ' '\012' < .deps/$(*F).pp \
+	  | sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
+	    >> .deps/$(*F).P; \
+	rm -f .deps/$(*F).pp
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am: install-pkgLTLIBRARIES
+install-data: install-data-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-pkgLTLIBRARIES
+uninstall: uninstall-am
+all-am: Makefile $(LTLIBRARIES)
+all-redirect: all-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+	$(mkinstalldirs)  $(DESTDIR)$(pkgdir)
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-rm -f Makefile $(CONFIG_CLEAN_FILES)
+	-rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am:  mostlyclean-pkgLTLIBRARIES mostlyclean-compile \
+		mostlyclean-libtool mostlyclean-tags mostlyclean-depend \
+		mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-pkgLTLIBRARIES clean-compile clean-libtool clean-tags \
+		clean-depend clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-pkgLTLIBRARIES distclean-compile \
+		distclean-libtool distclean-tags distclean-depend \
+		distclean-generic clean-am
+	-rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-pkgLTLIBRARIES \
+		maintainer-clean-compile maintainer-clean-libtool \
+		maintainer-clean-tags maintainer-clean-depend \
+		maintainer-clean-generic distclean-am
+	@echo "This command is intended for maintainers to use;"
+	@echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-pkgLTLIBRARIES distclean-pkgLTLIBRARIES \
+clean-pkgLTLIBRARIES maintainer-clean-pkgLTLIBRARIES \
+uninstall-pkgLTLIBRARIES install-pkgLTLIBRARIES mostlyclean-compile \
+distclean-compile clean-compile maintainer-clean-compile \
+mostlyclean-libtool distclean-libtool clean-libtool \
+maintainer-clean-libtool tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir mostlyclean-depend \
+distclean-depend clean-depend maintainer-clean-depend info-am info \
+dvi-am dvi check check-am installcheck-am installcheck install-exec-am \
+install-exec install-data-am install-data install-am install \
+uninstall-am uninstall all-redirect all-am all installdirs \
+mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/README	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,85 @@
+icqlib v1.0.0
+Denis V. Dmitrienko <denis@null.net>
+Bill Soudan <soudan@kde.org>
+
+DESCRIPTION
+-----------
+icqlib is the most feature complete, open source, library implementation
+of Mirabilis' ICQ protocol available on the Internet. icqlib currently
+supports approximately 90% of the ICQ UDP v5 protocol and 80% of the
+ICQ TCP v2 protocol, including new UIN registration, chat, and file
+transfer.
+
+Features:
+* written in C for portability - compiles on most Unices
+* supports multiple simultaneous connections to ICQ servers - more
+  than one UIN can log in and receive events
+* SOCKS5 firewall support for both UDP and TCP protocols
+* event driven, non-blocking interface
+* supports Russian language - automatically performs conversion from
+  Windows 1251 encoding to unix koi8 encoding
+
+DOWNLOAD
+--------
+Home page:
+      http://kicq.sourceforge.net/icqlib.shtml
+Direct download:
+      http://download.sourceforge.net/icqlib/icqlib-1.0.0.tar.gz
+      ftp://ftp.kde.org/pub/kde/unstable/apps/network/icqlib-1.0.0.tar.gz
+
+INSTALL
+-------
+This is very basic:
+      ./configure
+      make
+      su -c "make install"
+
+If you want to install in other place:
+      ./configure --prefix=/place/to/install/icqlib
+      make
+      make install
+
+You should have permissions to write in /place/to/install/icqlib or should
+install it from root:
+      su -c "make install"
+
+For more details read INSTALL file.
+
+BUGS
+----
+If you find one that isn't listed, submit your bugreport here:
+http://sourceforge.net/bugs/?group_id=384
+And if you have a fix for it, so much the better! Submit your patch
+here:
+http://sourceforge.net/patch/?group_id=384
+
+PARTICIPATION
+-------------
+You can participate in icqlib project in any way here:
+http://sourceforge.net/projects/icqlib
+Send your feature requests here:
+http://sourceforge.net/support/?group_id=384
+
+Please try to avoid abusing developers with direct email messages,
+especially if your question could be already answered somewhere in
+the project forums or mailing lists. Please use provided above web
+forms to submit your reports and requests. And of course, any kind of
+contributions and propositions are very appreciated and welcomed, and
+could be sent directly. Thank you for your understanding and patience.
+
+THANKS
+------
+To
+- Matthew Smith, Magnus Ihse, Jeremy Wise, Henrik Isaksson and other
+  people from ICQDev <icq-devel@lists.realminfo.com> and
+  micq <micq@phantom.iquest.net> mailing lists for their contribution
+  in icq protocol research
+- K Desktop Environment developers
+- icqlib and kicq users
+
+And finally
+- Linus Torvalds, Alan Cox and other Linux programmers for great OS
+
+--
+Enjoy!
+icqlib development team.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/VERSION	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,1 @@
+1.0.0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/chatsession.c	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,52 @@
+
+#include <stdlib.h>
+
+#include "chatsession.h"
+#include "list.h"
+
+icq_ChatSession *icq_ChatSessionNew(ICQLINK *icqlink) 
+{
+  icq_ChatSession *p=(icq_ChatSession *)malloc(sizeof(icq_ChatSession));
+
+  if (p)
+  {
+    p->remote_handle=0L;
+    p->status=0;
+    p->id=0L;
+    p->icqlink=icqlink;
+    list_insert(icqlink->icq_ChatSessions, 0, p);
+  }
+	
+  return p;
+}
+
+void icq_ChatSessionDelete(void *p)
+{
+  free(p);
+}
+
+void icq_ChatSessionClose(icq_ChatSession *p)
+{
+  list_remove(p->icqlink->icq_ChatSessions, p);
+  icq_ChatSessionDelete(p);
+}
+
+int _icq_FindChatSession(void *p, va_list data)
+{
+  DWORD uin=va_arg(data, DWORD);
+  return (((icq_ChatSession *)p)->remote_uin == uin);
+}
+
+icq_ChatSession *icq_FindChatSession(ICQLINK *icqlink, DWORD uin)
+{
+  return list_traverse(icqlink->icq_ChatSessions,
+    _icq_FindChatSession, uin);
+}
+
+void icq_ChatSessionSetStatus(icq_ChatSession *p, int status)
+{
+  p->status=status;
+  if(p->id)
+    if(p->icqlink->icq_RequestNotify)
+      (*p->icqlink->icq_RequestNotify)(p->icqlink, p->id, ICQ_NOTIFY_CHAT, status, 0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/chatsession.h	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,80 @@
+
+#ifndef _CHAT_SESSION_H
+#define _CHAT_SESSION_H
+
+#include "icq.h"
+#include "icqtypes.h"
+
+/* chat session statuses- request receiver */
+#define CHAT_STATUS_LISTENING    1
+#define CHAT_STATUS_CONNECTED    3
+#define CHAT_STATUS_WAIT_NAME    4
+#define CHAT_STATUS_WAIT_FONT    6
+
+/* chat session statuses- request sender */
+#define CHAT_STATUS_CONNECTING   2
+#define CHAT_STATUS_WAIT_ALLINFO 5
+
+/* once negotiation is complete, both sides enter ready state */
+#define CHAT_STATUS_READY        7
+
+/* chat session states:
+
+   accepting chat request 
+	 
+   1. remote user initiates chat by sending chat request to message listen 
+	    port
+	 2. local user accepts chat, ack packet sent back to remote user and
+	    chat listen port opened
+			* chat session created on local side with ID of ack packet
+			  LISTENING
+			* remote chat session created with ID of ack packet
+			  CONNECTING
+	 3. remote client connects to local chat listen port, sends hello and
+	    sends info packet with name and colors
+			* local chat session associated with new icq_TCPLink according to uin
+	 4.	local client sends back big info packet with name, colors, and font
+		  
+	 5. remote client sends font packet, connection is considered established
+	 
+	 sending chat request
+	 
+	 1. local user initiates chat by sending chat request to remote message
+	    listen port
+	 2. remote user accepts chat, ack packet received from remote client and
+	    remote client opens chat listen port
+	 3. local client connects to remote chat listen port, sends hello and
+	    sends info packet with name and colors
+	 4. remote client sends back big info packet with name, colors, and font
+	 5. local client sends font packet, connection is considered established
+
+   1. icq_RecvChatRequest - provides session ID (same as packet sequence)
+	 2. icq_SendChatAck - pass session ID
+	     ICQ_NOTIFY_CONNECTED
+			 ICQ_NOTIFY_SENT
+			 ICQ_NOTIFY_CHAT, CHAT_STATUS_LISTENING
+   3. ICQ_NOTIFY_CHAT, CHAT_STATUS_WAIT_NAME
+	 4. ICQ_NOTIFY_CHAT, CHAT_STATUS_WAIT_FONT
+	 5. ICQ_NOTIFY_CHAT, CHAT_STATUS_CONNECTED
+	    ICQ_NOTIFY_CHATDATA, ....
+			ICQ_NOTIFY_SUCCESS
+*/
+
+typedef struct icq_ChatSession_s {
+
+  DWORD id;
+  int status;
+  ICQLINK *icqlink;
+
+  DWORD remote_uin;
+  char *remote_handle;
+
+} icq_ChatSession;
+
+icq_ChatSession *icq_ChatSessionNew(ICQLINK *);
+void icq_ChatSessionDelete(void *);
+void icq_ChatSessionClose(icq_ChatSession *);
+void icq_ChatSessionSetStatus(icq_ChatSession *, int);
+icq_ChatSession *icq_FindChatSession(ICQLINK *, DWORD);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/contacts.c	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,109 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+$Id: contacts.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Log$
+Revision 1.1  2000/11/28 02:22:42  warmenhoven
+icq. whoop de doo
+
+Revision 1.4  2000/06/17 16:38:45  denis
+New parameter was added in icq_ContactSetVis() for setting/resetting
+'Visible to User' status.
+Port's type was changed to unsigned short in icq_UserOnline callback.
+
+Revision 1.3  2000/01/16 03:59:10  bills
+reworked list code so list_nodes don't need to be inside item structures,
+removed strlist code and replaced with generic list calls
+
+Revision 1.2  1999/07/23 12:28:00  denis
+Cleaned up.
+
+Revision 1.1  1999/07/18 20:11:48  bills
+added
+
+*/
+
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "icqtypes.h"
+#include "util.h"
+#include "icq.h"
+#include "list.h"
+#include "contacts.h"
+
+icq_ContactItem *icq_ContactNew(ICQLINK *link)
+{
+  icq_ContactItem *pcontact=
+    (icq_ContactItem *)malloc(sizeof(icq_ContactItem));
+
+  if(pcontact)
+    pcontact->icqlink=link;
+
+  return pcontact;
+}
+
+void icq_ContactDelete(void *p)
+{
+  free(p);
+}
+
+void icq_ContactAdd(ICQLINK *link, DWORD cuin)
+{
+  icq_ContactItem *p = icq_ContactNew(link);
+  p->uin = cuin;
+  p->vis_list = FALSE;
+
+  list_enqueue(link->icq_ContactList, p);
+}
+
+void icq_ContactRemove(ICQLINK *link, DWORD cuin)
+{
+  icq_ContactItem *pcontact=icq_ContactFind(link, cuin);
+
+  if (pcontact)
+  {
+    list_remove(link->icq_ContactList, pcontact);
+    icq_ContactDelete(pcontact);
+  }
+}
+
+void icq_ContactClear(ICQLINK *link)
+{
+  list_delete(link->icq_ContactList, icq_ContactDelete);
+  link->icq_ContactList=list_new();
+}
+
+int _icq_ContactFind(void *p, va_list data)
+{
+  DWORD uin=va_arg(data, DWORD);
+
+  return (((icq_ContactItem *)p)->uin == uin);
+}
+
+icq_ContactItem *icq_ContactFind(ICQLINK *link, DWORD cuin)
+{
+  return list_traverse(link->icq_ContactList, _icq_ContactFind, cuin);
+}
+
+void icq_ContactSetVis(ICQLINK *link, DWORD cuin, BYTE vu)
+{
+  icq_ContactItem *p = icq_ContactFind(link, cuin);
+  if(p)
+    p->vis_list = vu;
+}
+
+icq_ContactItem *icq_ContactGetFirst(ICQLINK *link)
+{
+  return list_first(link->icq_ContactList);
+}
+
+icq_ContactItem *icq_ContactGetNext(icq_ContactItem *pcontact)
+{
+  list_node *p=list_find(pcontact->icqlink->icq_ContactList, pcontact);
+
+  if (p && p->next)
+    return p->next->item;
+  else
+    return 0L;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/contacts.h	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,25 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+#ifndef _CONTACTS_H
+#define _CONTACTS_H
+
+#include "icq.h"
+#include "icqtypes.h"
+
+typedef struct icq_ContItem
+{
+  ICQLINK *icqlink;
+  unsigned long uin;
+  int vis_list;
+  unsigned long remote_ip;
+  unsigned long remote_real_ip;
+  unsigned long remote_port;
+  unsigned char tcp_flag;
+} icq_ContactItem;  
+
+icq_ContactItem *icq_ContactNew(ICQLINK *link);
+void icq_ContactDelete(void *pcontact);
+icq_ContactItem *icq_ContactFind(ICQLINK *link, DWORD cuin);
+icq_ContactItem *icq_ContactGetFirst(ICQLINK *link);
+icq_ContactItem *icq_ContactGetNext(icq_ContactItem *pcontact);
+
+#endif /* _CONTACTS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/cyrillic.c	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,138 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+$Id: cyrillic.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Log$
+Revision 1.1  2000/11/28 02:22:42  warmenhoven
+icq. whoop de doo
+
+Revision 1.7  2000/05/21 17:41:14  denis
+Applied patch for russian letters IO and io by
+Vladimir Eltchinov <elik@design.ru>
+
+Revision 1.6  2000/02/07 02:31:37  bills
+added icq_RusConv_n
+
+Revision 1.5  1999/09/29 16:45:26  denis
+Cleanups
+
+Revision 1.4  1999/07/16 12:08:20  denis
+Cleaned up.
+
+Revision 1.3  1999/07/12 15:13:29  cproch
+- added definition of ICQLINK to hold session-specific global variabled
+  applications which have more than one connection are now possible
+- changed nearly every function defintion to support ICQLINK parameter
+
+Revision 1.2  1999/04/14 14:44:30  denis
+Switched from icq_Log callback to icq_FmtLog function.
+
+Revision 1.1  1999/03/24 11:37:35  denis
+Underscored files with TCP stuff renamed.
+TCP stuff cleaned up
+Function names changed to corresponding names.
+icqlib.c splitted to many small files by subject.
+C++ comments changed to ANSI C comments.
+
+*/
+
+#include "icqtypes.h"
+#include "icq.h"
+#include "icqlib.h"
+#include "util.h"
+
+BYTE kw[] = {128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+             144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+             160,161,162,184,164,165,166,167,168,169,170,171,172,173,174,175,
+             176,177,178,168,180,181,182,183,184,185,186,187,188,189,190,191,
+             254,224,225,246,228,229,244,227,245,232,233,234,235,236,237,238,
+             239,255,240,241,242,243,230,226,252,251,231,248,253,249,247,250,
+             222,192,193,214,196,197,212,195,213,200,201,202,203,204,205,206,
+             207,223,208,209,210,211,198,194,220,219,199,216,221,217,215,218};
+
+BYTE wk[] = {128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
+             144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
+             160,161,162,163,164,165,166,167,179,169,170,171,172,173,174,175,
+             176,177,178,179,180,181,182,183,163,185,186,187,188,189,190,191,
+             225,226,247,231,228,229,246,250,233,234,235,236,237,238,239,240,
+             242,243,244,245,230,232,227,254,251,253,255,249,248,252,224,241,
+             193,194,215,199,196,197,214,218,201,202,203,204,205,206,207,208,
+             210,211,212,213,198,200,195,222,219,221,223,217,216,220,192,209};
+
+/********************************************************
+Russian language ICQ fix.
+Usual Windows ICQ users do use Windows 1251 encoding but
+unix users do use koi8 encoding, so we need to convert it.
+This function will convert string from windows 1251 to koi8
+or from koi8 to windows 1251.
+Andrew Frolov dron@ilm.net
+*********************************************************/
+
+extern int icq_Russian;
+
+void icq_RusConv(const char to[4], char *t_in)
+{
+  BYTE *table;
+  int i;
+
+/* 6-17-1998 by Linux_Dude
+ * Moved initialization of table out front of 'if' block to prevent compiler
+ * warning. Improved error message, and now return without performing string
+ * conversion to prevent addressing memory out of range (table pointer would
+ * previously have remained uninitialized (= bad)).
+ */
+
+  table = wk;
+  if(strcmp(to, "kw") == 0)
+    table = kw;
+  else if(strcmp(to, "wk") != 0)
+  {
+    icq_FmtLog(NULL, ICQ_LOG_ERROR, "Unknown option in call to Russian Convert\n");
+    return;
+  }
+      
+/* End Linux_Dude's changes ;) */
+
+  if(icq_Russian)
+  {
+    for(i=0;t_in[i]!=0;i++)
+    {
+      t_in[i] &= 0377;
+      if(t_in[i] & 0200)
+        t_in[i] = table[t_in[i] & 0177];
+    }
+  }
+}
+
+void icq_RusConv_n(const char to[4], char *t_in, int len)
+{
+  BYTE *table;
+  int i;
+
+/* 6-17-1998 by Linux_Dude
+ * Moved initialization of table out front of 'if' block to prevent compiler
+ * warning. Improved error message, and now return without performing string
+ * conversion to prevent addressing memory out of range (table pointer would
+ * previously have remained uninitialized (= bad)).
+ */
+
+  table = wk;
+  if(strcmp(to, "kw") == 0)
+    table = kw;
+  else if(strcmp(to, "wk") != 0)
+  {
+    icq_FmtLog(NULL, ICQ_LOG_ERROR, "Unknown option in call to Russian Convert\n");
+    return;
+  }
+      
+/* End Linux_Dude's changes ;) */
+
+  if(icq_Russian)
+  {
+    for(i=0;i < len;i++)
+    {
+      t_in[i] &= 0377;
+      if(t_in[i] & 0200)
+        t_in[i] = table[t_in[i] & 0177];
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/filesession.c	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,233 @@
+#include <stdlib.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#ifdef _MSVC_
+#include <io.h>
+#define open _open
+#define close _close
+#define read _read
+#define write _write
+#endif
+
+#include "filesession.h"
+#include "list.h"
+#include "icqpacket.h"
+#include "stdpackets.h"
+
+icq_FileSession *icq_FileSessionNew(ICQLINK *icqlink)
+{
+  icq_FileSession *p=(icq_FileSession *)malloc(sizeof(icq_FileSession));
+
+  if (p)
+  {
+    p->status=0;
+    p->id=0L;
+    p->icqlink=icqlink;
+    p->current_fd=-1;
+    p->current_file_num=0;
+    p->current_file_progress=0;
+    p->current_file_size=0;
+    p->files=0L;
+    p->current_speed=100;
+    p->total_bytes=0;
+    p->total_files=0;
+    p->total_transferred_bytes=0;
+    p->working_dir[0]=0;
+    list_insert(icqlink->icq_FileSessions, 0, p);
+  }
+	
+  return p;
+}
+
+void icq_FileSessionDelete(void *pv)
+{
+  icq_FileSession *p=(icq_FileSession *)pv;
+
+  if(p->files) {
+    char **p2=p->files;
+    while(*p2)
+      free(*(p2++));
+    free(p->files);
+  }
+
+  if (p->current_fd > -1 ) {
+     close(p->current_fd);
+     p->current_fd=-1;
+  }
+
+  free(p);
+}
+
+int _icq_FindFileSession(void *p, va_list data)
+{
+  icq_FileSession *psession=(icq_FileSession *)p;
+  DWORD uin=va_arg(data, DWORD);
+  unsigned long id=va_arg(data, unsigned long);
+  
+  return (psession->remote_uin == uin) && ( id ? (psession->id == id) : 1 );
+
+}
+
+icq_FileSession *icq_FindFileSession(ICQLINK *icqlink, DWORD uin,
+  unsigned long id)
+{
+  return list_traverse(icqlink->icq_FileSessions, _icq_FindFileSession, 
+    uin, id);
+}
+
+void icq_FileSessionSetStatus(icq_FileSession *p, int status)
+{
+  if(status!=p->status)
+  {
+    p->status=status;
+    if(p->id && p->icqlink->icq_RequestNotify)
+      (*p->icqlink->icq_RequestNotify)(p->icqlink, p->id, ICQ_NOTIFY_FILE,
+       status, 0);
+  }
+}
+
+void icq_FileSessionSetHandle(icq_FileSession *p, const char *handle)
+{
+  strncpy(p->remote_handle, handle, 64);
+}
+
+void icq_FileSessionSetCurrentFile(icq_FileSession *p, const char *filename)
+{
+  struct stat file_status;
+  char file[1024];
+
+  strcpy(file, p->working_dir);
+  strcat(file, filename);
+
+  if (p->current_fd>-1) {
+    close(p->current_fd);
+    p->current_fd=-1;
+  }
+
+  strncpy(p->current_file, file, 64);
+  p->current_file_progress=0;
+
+  /* does the file already exist? */
+  if (stat(file, &file_status)==0) {
+    p->current_file_progress=file_status.st_size;
+    p->total_transferred_bytes+=file_status.st_size;
+    p->current_fd=open(file, O_WRONLY | O_APPEND);
+  } else {
+#ifdef _WIN32
+    p->current_fd=open(file, O_WRONLY | O_CREAT);
+#else
+    p->current_fd=open(file, O_WRONLY | O_CREAT, S_IRWXU);
+#endif
+  }
+
+  /* make sure we have a valid filehandle */
+  if (p->current_fd == -1)
+    perror("couldn't open file: ");
+      
+}
+
+void icq_FileSessionPrepareNextFile(icq_FileSession *p)
+{
+  int i=0;
+  char **files=p->files;
+
+  p->current_file_num++;
+
+  while(*files) {
+    i++;
+    if(i==p->current_file_num)
+      break;
+    else
+      files++;
+  }
+
+  if(*files) {
+    struct stat file_status;
+
+    if (p->current_fd>-1) {
+       close(p->current_fd);
+       p->current_fd=-1;
+    }
+
+    if (stat(*files, &file_status)==0) {
+       char *basename=*files;
+       char *pos=strrchr(basename, '/');
+       if(pos) basename=pos+1;
+       strncpy(p->current_file, basename, 64);
+       p->current_file_progress=0;
+       p->current_file_size=file_status.st_size;
+       p->current_fd=open(*files, O_RDONLY);
+    }
+
+    /* make sure we have a valid filehandle */
+    if (p->current_fd == -1)
+       perror("couldn't open file: ");
+  }     
+}        
+
+void icq_FileSessionSendData(icq_FileSession *p)
+{
+  /* for now just send a packet at a time */
+  char buffer[2048];
+  int count=read(p->current_fd, buffer, 2048);
+
+  if(count>0) {
+      icq_Packet *p2=icq_TCPCreateFile06Packet(count, buffer);
+      icq_TCPLinkSend(p->tcplink, p2);
+      p->total_transferred_bytes+=count;
+      p->current_file_progress+=count;
+      icq_FileSessionSetStatus(p, FILE_STATUS_SENDING);
+      
+      if (p->icqlink->icq_RequestNotify)
+        (*p->icqlink->icq_RequestNotify)(p->icqlink, p->id,
+          ICQ_NOTIFY_FILEDATA, count, NULL); 
+  }
+
+  /* done transmitting if read returns less that 2048 bytes */
+  if(count<2048)
+      icq_FileSessionClose(p);
+
+  return;
+}
+
+/* public */
+
+void icq_FileSessionSetSpeed(icq_FileSession *p, int speed)
+{
+  icq_Packet *packet=icq_TCPCreateFile05Packet(speed);
+
+  icq_TCPLinkSend(p->tcplink, packet);
+}
+
+void icq_FileSessionClose(icq_FileSession *p)
+{
+  icq_TCPLink *plink=p->tcplink;
+
+  /* TODO: handle closing already unallocated filesession? */
+
+  /* if we're attached to a tcplink, unattach so the link doesn't try
+   * to close us, and then close the tcplink */
+  if (plink)
+  {
+    plink->session=0L;
+    icq_TCPLinkClose(plink);
+  }
+
+  icq_FileSessionDelete(p);
+
+  list_remove(p->icqlink->icq_FileSessions, p);		
+}   
+
+void icq_FileSessionSetWorkingDir(icq_FileSession *p, const char *dir)
+{
+  strncpy(p->working_dir, dir, 512);
+}  
+
+void icq_FileSessionSetFiles(icq_FileSession *p, char **files)
+{
+  p->files=files;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/filesession.h	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,17 @@
+
+#ifndef _FILE_SESSION_H
+#define _FILE_SESSION_H
+
+#include "icq.h"
+#include "icqtypes.h"
+
+icq_FileSession *icq_FileSessionNew(ICQLINK *);
+void icq_FileSessionDelete(void *);
+void icq_FileSessionSetStatus(icq_FileSession *, int);
+icq_FileSession *icq_FindFileSession(ICQLINK *, unsigned long, unsigned long);
+void icq_FileSessionSetHandle(icq_FileSession *, const char *);
+void icq_FileSessionSetCurrentFile(icq_FileSession *, const char *);
+void icq_FileSessionPrepareNextFile(icq_FileSession *);
+void icq_FileSessionSendData(icq_FileSession *);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/gaim_icq.c	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,292 @@
+#include <gtk/gtk.h>
+#include "icq.h"   /* well, we're doing ICQ, right? */
+#include "multi.h" /* needed for gaim_connection */
+#include "prpl.h"  /* needed for prpl */
+#include "gaim.h"  /* needed for every other damn thing */
+
+struct icq_data {
+	ICQLINK *link;
+	int cur_status;
+	int tcp_timer;
+	int ack_timer;
+};
+
+static struct gaim_connection *find_gaim_conn_by_icq_link(ICQLINK *link) {
+	GSList *c = connections;
+	struct gaim_connection *gc = NULL;
+	struct icq_data *id;
+
+	while (c) {
+		gc = (struct gaim_connection *)c->data;
+		if (gc->protocol == PROTO_ICQ) {
+			id = (struct icq_data *)gc->proto_data;
+			if (id->link == link)
+				break;
+		}
+		gc = NULL;
+		c = c->next;
+	}
+
+	return gc;
+}
+
+static char *icq_name() {
+	return "ICQ";
+}
+
+static void icq_do_log(ICQLINK *link, time_t time, unsigned char level, const char *log) {
+	debug_printf("ICQ debug %d: %s", level, log);
+}
+
+static gint icq_tcp_timer(ICQLINK *link) {
+	icq_TCPMain(link);
+	return TRUE;
+}
+
+static void icq_callback(gpointer data, gint source, GdkInputCondition condition) {
+	struct gaim_connection *gc = (struct gaim_connection *)data;
+	struct icq_data *id = (struct icq_data *)gc->proto_data;
+	debug_printf("ICQ Callback handler\n");
+
+	icq_HandleServerResponse(id->link);
+}
+
+static void icq_online(ICQLINK *link) {
+	struct gaim_connection *gc = find_gaim_conn_by_icq_link(link);
+	struct icq_data *id = (struct icq_data *)gc->proto_data;
+	debug_printf("%s is now online.\n", gc->username);
+	account_online(gc);
+	serv_finish_login(gc);
+
+	if (bud_list_cache_exists(gc))
+		do_import(NULL, gc);
+
+	icq_ChangeStatus(id->link, STATUS_ONLINE);
+}
+
+static void icq_logged_off(ICQLINK *link) {
+	struct gaim_connection *gc = find_gaim_conn_by_icq_link(link);
+	struct icq_data *id = (struct icq_data *)gc->proto_data;
+	int icqSocket;
+
+	gtk_timeout_remove(id->tcp_timer);
+	gdk_input_remove(gc->inpa);
+
+	if (icq_Connect(link, "icq.mirabilis.com", 4000) < 1) {
+		hide_login_progress(gc, "Unable to connect");
+		g_free(id);
+		signoff(gc);
+		return;
+	}
+
+	icqSocket = icq_GetSok(link);
+	gc->inpa = gdk_input_add(icqSocket, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, icq_callback, gc);
+
+	icq_Login(link, STATUS_ONLINE);
+	id->cur_status = STATUS_ONLINE;
+
+	id->tcp_timer = gtk_timeout_add(100, (GtkFunction)icq_tcp_timer, link);
+}
+
+static void icq_msg_incoming(ICQLINK *link, unsigned long uin, unsigned char hour, unsigned char minute,
+			unsigned char day, unsigned char month, unsigned short year, const char *data) {
+	struct gaim_connection *gc = find_gaim_conn_by_icq_link(link);
+	char buf[256], *tmp = g_strdup(data);
+	g_snprintf(buf, sizeof buf, "%lu", uin);
+	serv_got_im(gc, buf, tmp, 0);
+	g_free(tmp);
+}
+
+static void icq_user_online(ICQLINK *link, unsigned long uin, unsigned long status,
+				unsigned long ip, unsigned short port, unsigned long real_ip,
+				unsigned char tcp_flags) {
+	struct gaim_connection *gc = find_gaim_conn_by_icq_link(link);
+	char buf[256]; g_snprintf(buf, sizeof buf, "%lu", uin);
+	serv_got_update(gc, buf, 1, 0, 0, 0, (status==STATUS_ONLINE) ? UC_NORMAL : UC_UNAVAILABLE, 0);
+}
+
+static void icq_user_offline(ICQLINK *link, unsigned long uin) {
+	struct gaim_connection *gc = find_gaim_conn_by_icq_link(link);
+	char buf[256]; g_snprintf(buf, sizeof buf, "%lu", uin);
+	serv_got_update(gc, buf, 0, 0, 0, 0, 0, 0);
+}
+
+static void icq_user_status(ICQLINK *link, unsigned long uin, unsigned long status) {
+	struct gaim_connection *gc = find_gaim_conn_by_icq_link(link);
+	char buf[256]; g_snprintf(buf, sizeof buf, "%lu", uin);
+	serv_got_update(gc, buf, 1, 0, 0, 0, (status==STATUS_ONLINE) ? UC_NORMAL : UC_UNAVAILABLE, 0);
+}
+
+static gint icq_set_timeout_cb(struct icq_data *id) {
+	icq_HandleTimeout(id->link);
+	id->ack_timer = -1;
+	return FALSE;
+}
+
+static void icq_set_timeout(ICQLINK *link, long interval) {
+	struct gaim_connection *gc = find_gaim_conn_by_icq_link(link);
+	struct icq_data *id = (struct icq_data *)gc->proto_data;
+
+	debug_printf("icq_SetTimeout: %ld\n", interval);
+	if (interval > 0 && id->ack_timer < 1)
+		id->ack_timer = gtk_timeout_add(interval * 1000, (GtkFunction)icq_set_timeout_cb, id);
+	else if (id->ack_timer > 0) {
+		gtk_timeout_remove(id->ack_timer);
+		id->ack_timer = -1;
+	}
+}
+
+static void icq_url_incoming(struct icq_link *link, unsigned long uin, unsigned char hour,
+				unsigned char minute, unsigned char day, unsigned char month,
+				unsigned short year, const char *url, const char *descr) {
+	struct gaim_connection *gc = find_gaim_conn_by_icq_link(link);
+	int len = strlen(url) + strlen(descr) + 25; /* 25 is straight out of my ass */
+	char *msg = g_malloc(len), buf[256];
+	g_snprintf(msg, len, "<A HREF=\"%s\">%s</A>", url, descr);
+	g_snprintf(buf, 256, "%lu", uin);
+	serv_got_im(gc, buf, msg, 0);
+	g_free(msg);
+}
+
+static void icq_wrong_passwd(struct icq_link *link) {
+	struct gaim_connection *gc = find_gaim_conn_by_icq_link(link);
+	hide_login_progress(gc, "Invalid password.");
+	signoff(gc);
+}
+
+static void icq_invalid_uin(struct icq_link *link) {
+	struct gaim_connection *gc = find_gaim_conn_by_icq_link(link);
+	hide_login_progress(gc, "Invalid UIN.");
+	signoff(gc);
+}
+
+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);
+	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;
+	link->icq_RecvURL = icq_url_incoming;
+	link->icq_UserOnline = icq_user_online;
+	link->icq_UserOffline = icq_user_offline;
+	link->icq_UserStatusUpdate = icq_user_status;
+	link->icq_WrongPassword = icq_wrong_passwd;
+	link->icq_InvalidUIN = icq_invalid_uin;
+	link->icq_Log = icq_do_log;
+	link->icq_SetTimeout = icq_set_timeout;
+
+	icq_UnsetProxy(link);
+
+	if (icq_Connect(link, "icq.mirabilis.com", 4000) < 1) {
+		hide_login_progress(gc, "Unable to connect");
+		g_free(id);
+		signoff(gc);
+		return;
+	}
+
+	icqSocket = icq_GetSok(link);
+	gc->inpa = gdk_input_add(icqSocket, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, icq_callback, gc);
+
+	icq_Login(link, STATUS_ONLINE);
+	id->cur_status = STATUS_ONLINE;
+
+	id->tcp_timer = gtk_timeout_add(100, (GtkFunction)icq_tcp_timer, link);
+
+	set_login_progress(gc, 0, "Connecting...");
+}
+
+static void icq_close(struct gaim_connection *gc) {
+	struct icq_data *id = (struct icq_data *)gc->proto_data;
+
+	gtk_timeout_remove(id->tcp_timer);
+	gdk_input_remove(gc->inpa);
+	icq_Logout(id->link);
+	icq_Disconnect(id->link);
+	icq_Done(id->link);
+	g_free(id->link);
+}
+
+static struct prpl *my_protocol = NULL;
+
+static void icq_send_msg(struct gaim_connection *gc, char *who, char *msg, int away) {
+	struct icq_data *id = (struct icq_data *)gc->proto_data;
+	icq_SendMessage(id->link, atol(who), msg, !away);
+}
+
+static void icq_keepalive(struct gaim_connection *gc) {
+	struct icq_data *id = (struct icq_data *)gc->proto_data;
+	icq_KeepAlive(id->link);
+}
+
+static void icq_add_buddy(struct gaim_connection *gc, char *who) {
+	struct icq_data *id = (struct icq_data *)gc->proto_data;
+	icq_ContactAdd(id->link, atol(who));
+	icq_ContactSetVis(id->link, atol(who), TRUE);
+	icq_SendNewUser(id->link, atol(who));
+}
+
+static void icq_add_buddies(struct gaim_connection *gc, GList *whos) {
+	struct icq_data *id = (struct icq_data *)gc->proto_data;
+	while (whos) {
+		icq_ContactAdd(id->link, atol(whos->data));
+		icq_ContactSetVis(id->link, atol(whos->data), TRUE);
+		icq_SendNewUser(id->link, atol(whos->data));
+		whos = whos->next;
+	}
+}
+
+static void icq_rem_buddy(struct gaim_connection *gc, char *who) {
+	struct icq_data *id = (struct icq_data *)gc->proto_data;
+	icq_ContactRemove(id->link, atol(who));
+}
+
+static void icq_set_away(struct gaim_connection *gc, char *msg) {
+	struct icq_data *id = (struct icq_data *)gc->proto_data;
+
+	if (msg && msg[0]) {
+		icq_ChangeStatus(id->link, STATUS_NA);
+	} else {
+		icq_ChangeStatus(id->link, STATUS_ONLINE);
+	}
+}
+
+static void icq_init(struct prpl *ret) {
+	ret->protocol = PROTO_ICQ;
+	ret->name = icq_name;
+	ret->login = icq_login;
+	ret->close = icq_close;
+	ret->send_im = icq_send_msg;
+	ret->add_buddy = icq_add_buddy;
+	ret->add_buddies = icq_add_buddies;
+	ret->remove_buddy = icq_rem_buddy;
+	ret->set_away = icq_set_away;
+	ret->keepalive = icq_keepalive;
+
+	my_protocol = ret;
+}
+
+char *gaim_plugin_init(GModule *handle) {
+	load_protocol(icq_init);
+	return NULL;
+}
+
+void gaim_plugin_remove() {
+	struct prpl *p = find_prpl(PROTO_ICQ);
+	if (p == my_protocol)
+		unload_protocol(p);
+}
+
+char *name() {
+	return "ICQ";
+}
+
+char *description() {
+	return "Allows gaim to use the ICQ protocol";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/icq.h	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,368 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+#ifndef _ICQ_H_
+#define _ICQ_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define ICQLIBVER   0x010000
+#define ICQLIBMAJOR 1
+#define ICQLIBMINOR 0
+#define ICQLIBMICRO 0
+
+#include <time.h>
+
+#ifndef _WIN32
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+#ifdef _WIN32
+#include <winsock.h>
+#endif
+
+#define ICQ_LOG_OFF     0
+#define ICQ_LOG_FATAL   1
+#define ICQ_LOG_ERROR   2
+#define ICQ_LOG_WARNING 3
+#define ICQ_LOG_MESSAGE 4
+
+#define STATUS_OFFLINE     (-1L)
+#define STATUS_ONLINE      0x0000L
+#define STATUS_AWAY        0x0001L
+#define STATUS_DND         0x0002L /* 0x13L */
+#define STATUS_NA          0x0004L /* 0x05L */
+#define STATUS_OCCUPIED    0x0010L /* 0x11L */
+#define STATUS_FREE_CHAT   0x0020L
+#define STATUS_INVISIBLE   0x0100L
+
+#define ICQ_SEND_THRUSERVER       0
+#define ICQ_SEND_DIRECT           1
+#define ICQ_SEND_BESTWAY          2
+
+#define ICQ_NOTIFY_SUCCESS        0
+#define ICQ_NOTIFY_FAILED         1
+#define ICQ_NOTIFY_CONNECTING     2
+#define ICQ_NOTIFY_CONNECTED      3
+#define ICQ_NOTIFY_SENT           4
+#define ICQ_NOTIFY_ACK            5
+
+#define ICQ_NOTIFY_CHAT           6
+#define ICQ_NOTIFY_CHATDATA       7
+
+#define ICQ_NOTIFY_FILE           10
+#define ICQ_NOTIFY_FILESESSION    11
+#define ICQ_NOTIFY_FILEDATA       12
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct 
+{
+  const char *name;
+  unsigned short code;
+} icq_ArrayType;
+
+typedef struct icq_link
+{
+  /* General */
+  unsigned long icq_Uin;
+  unsigned long icq_OurIP;          /* HOST byteorder */
+  unsigned short icq_OurPort;       /* HOST byteorder */
+  void *icq_ContactList;
+  unsigned long icq_Status;
+  char *icq_Password;
+  char *icq_Nick;
+
+  /* UDP stuff */
+  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;
+  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;
+
+  /* SOCKS5 Proxy stuff */
+  unsigned char icq_UseProxy;
+  char *icq_ProxyHost;
+  unsigned long icq_ProxyIP;        /* HOST byteorder */
+  unsigned short icq_ProxyPort;     /* HOST byteorder */
+  int  icq_ProxyAuth;
+  char *icq_ProxyName;
+  char *icq_ProxyPass;
+  int icq_ProxySok;
+  unsigned short icq_ProxyOurPort;  /* HOST byteorder */
+  unsigned long icq_ProxyDestIP;    /* HOST byteorder */
+  unsigned short icq_ProxyDestPort; /* HOST byteorder */
+
+  /*** Callbacks ***/
+  void (*icq_Logged)(struct icq_link *link);
+  void (*icq_Disconnected)(struct icq_link *link);
+  void (*icq_RecvMessage)(struct icq_link *link, unsigned long uin,
+       unsigned char hour, unsigned char minute, unsigned char day,
+       unsigned char month, unsigned short year, const char *msg);
+  void (*icq_RecvURL)(struct icq_link *link, unsigned long uin,
+       unsigned char hour, unsigned char minute, unsigned char day,
+       unsigned char month, unsigned short year, const char *url,
+       const char *descr);
+  void (*icq_RecvWebPager)(struct icq_link *link,unsigned char hour,
+       unsigned char minute, unsigned char day, unsigned char month,
+       unsigned short year, const char *nick, const char *email,
+       const char *msg);
+  void (*icq_RecvMailExpress)(struct icq_link *link,unsigned char hour,
+       unsigned char minute, unsigned char day, unsigned char month,
+       unsigned short year, const char *nick, const char *email,
+       const char *msg);
+  void (*icq_RecvChatReq)(struct icq_link *link, unsigned long uin,
+       unsigned char hour, unsigned char minute, unsigned char day,
+       unsigned char month, unsigned short year, const char *descr,
+       unsigned long seq);
+  void (*icq_RecvFileReq)(struct icq_link *link, unsigned long uin,
+       unsigned char hour, unsigned char minute, unsigned char day,
+       unsigned char month, unsigned short year, const char *descr,
+       const char *filename, unsigned long filesize, unsigned long seq);
+  void (*icq_RecvAdded)(struct icq_link *link, unsigned long uin,
+       unsigned char hour, unsigned char minute, unsigned char day,
+       unsigned char month, unsigned short year, const char *nick,
+       const char *first, const char *last, const char *email);
+  void (*icq_RecvAuthReq)(struct icq_link *link, unsigned long uin,
+       unsigned char hour, unsigned char minute, unsigned char day,
+       unsigned char month, unsigned short year, const char *nick,
+       const char *first, const char *last, const char *email,
+       const char *reason);
+  void (*icq_UserFound)(struct icq_link *link, unsigned long uin,
+       const char *nick, const char *first, const char *last,
+       const char *email, char auth);
+  void (*icq_SearchDone)(struct icq_link *link);
+  void (*icq_UserOnline)(struct icq_link *link, unsigned long uin,
+       unsigned long status, unsigned long ip, unsigned short port,
+       unsigned long real_ip, unsigned char tcp_flag );
+  void (*icq_UserOffline)(struct icq_link *link, unsigned long uin);
+  void (*icq_UserStatusUpdate)(struct icq_link *link, unsigned long uin,
+       unsigned long status);
+  void (*icq_InfoReply)(struct icq_link *link, unsigned long uin,
+       const char *nick, const char *first, const char *last,
+       const char *email, char auth);
+  void (*icq_ExtInfoReply)(struct icq_link *link, unsigned long uin,
+       const char *city, unsigned short country_code, char country_stat,
+       const char *state, unsigned short age, char gender,
+       const char *phone, const char *hp, const char *about);
+  void (*icq_WrongPassword)(struct icq_link *link);
+  void (*icq_InvalidUIN)(struct icq_link *link);
+  void (*icq_Log)(struct icq_link *link, time_t time, unsigned char level,
+       const char *str);
+  void (*icq_SrvAck)(struct icq_link *link, unsigned short seq);
+  void (*icq_RequestNotify)(struct icq_link *link, unsigned long id, int result,
+       unsigned int length, void *data);
+  void (*icq_NewUIN)(struct icq_link *link, unsigned long uin);
+  void (*icq_SetTimeout)(struct icq_link *link, long interval);
+  void (*icq_MetaUserFound)(struct icq_link *link, unsigned short seq2,
+       unsigned long uin, const char *nick, const char *first,
+       const char *last, const char *email, char auth);
+  void (*icq_MetaUserInfo)(struct icq_link *link, unsigned short seq2,
+       const char *nick, const char *first, const char *last,
+       const char *pri_eml, const char *sec_eml, const char *old_eml,
+       const char *city, const char *state, const char *phone, const char *fax,
+       const char *street, const char *cellular, unsigned long zip,
+       unsigned short country, unsigned char timezone, unsigned char auth,
+       unsigned char webaware, unsigned char hideip);
+  void (*icq_MetaUserWork)(struct icq_link *link, unsigned short seq2,
+       const char *wcity, const char *wstate, const char *wphone,
+       const char *wfax, const char *waddress, unsigned long wzip,
+       unsigned short wcountry, const char *company, const char *department,
+       const char *job, unsigned short occupation, const char *whomepage);
+  void (*icq_MetaUserMore)(struct icq_link *link, unsigned short seq2,
+       unsigned short age, unsigned char gender, const char *homepage,
+       unsigned char byear, unsigned char bmonth, unsigned char bday,
+       unsigned char lang1, unsigned char lang2, unsigned char lang3);
+  void (*icq_MetaUserAbout)(struct icq_link *link, unsigned short seq2,
+       const char *about);
+  void (*icq_MetaUserInterests)(struct icq_link *link, unsigned short seq2,
+       unsigned char num, unsigned short icat1, const char *int1,
+       unsigned short icat2, const char *int2, unsigned short icat3,
+       const char *int3, unsigned short icat4, const char *int4);
+  void (*icq_MetaUserAffiliations)(struct icq_link *link, unsigned short seq2,
+       unsigned char anum, unsigned short acat1, const char *aff1,
+       unsigned short acat2, const char *aff2, unsigned short acat3,
+       const char *aff3, unsigned short acat4, const char *aff4,
+       unsigned char bnum, unsigned short bcat1, const char *back1,
+       unsigned short bcat2, const char *back2, unsigned short bcat3,
+       const char *back3, unsigned short bcat4, const char *back4);
+  void (*icq_MetaUserHomePageCategory)(struct icq_link *link,
+       unsigned short seq2, unsigned char num, unsigned short hcat1,
+       const char *htext1);
+} ICQLINK;
+
+extern int icq_Russian;
+extern unsigned char icq_LogLevel;
+extern icq_ArrayType icq_Countries[];
+
+void icq_SetProxy(ICQLINK *link, const char *phost, unsigned short pport,
+     int pauth, const char *pname, const char *ppass);
+void icq_UnsetProxy(ICQLINK *link);
+
+void icq_Init(ICQLINK *link, unsigned long uin, const char *password,
+     const char *nick);
+void icq_Done(ICQLINK *link);
+int icq_Connect(ICQLINK *link, const char *hostname, int port);
+void icq_Disconnect(ICQLINK *link);
+int icq_GetSok(ICQLINK *link);
+int icq_GetProxySok(ICQLINK *link);
+void icq_HandleServerResponse(ICQLINK *link);
+void icq_HandleProxyResponse(ICQLINK *link);
+void icq_HandleTimeout(ICQLINK *link);
+void icq_Main(ICQLINK *link);
+unsigned short icq_KeepAlive(ICQLINK *link);
+void icq_Login(ICQLINK *link, unsigned long status);
+void icq_Logout(ICQLINK *link);
+void icq_SendContactList(ICQLINK *link);
+void icq_SendVisibleList(ICQLINK *link);
+void icq_SendNewUser(ICQLINK * link, unsigned long uin);
+unsigned long icq_SendMessage(ICQLINK *link, unsigned long uin,
+     const char *text, unsigned char thruSrv);
+unsigned long icq_SendURL(ICQLINK *link, unsigned long uin, const char *url,
+     const char *descr, unsigned char thruSrv);
+void icq_ChangeStatus(ICQLINK *link, unsigned long status);
+unsigned short icq_SendInfoReq(ICQLINK *link, unsigned long uin);
+unsigned short icq_SendExtInfoReq(ICQLINK *link, unsigned long uin);
+unsigned short icq_SendAuthMsg(ICQLINK *link, unsigned long uin);
+void icq_SendSearchReq(ICQLINK *link, const char *email, const char *nick,
+     const char* first, const char* last);
+void icq_SendSearchUINReq(ICQLINK *link, unsigned long uin);
+
+const char *icq_GetCountryName(unsigned short code);
+const char *icq_GetMetaOccupationName(unsigned short code);
+const char *icq_GetMetaBackgroundName(unsigned short code);
+const char *icq_GetMetaAffiliationName(unsigned short code);
+const char *icq_GetMetaLanguageName(unsigned short code);
+void icq_RegNewUser(ICQLINK *link, const char *pass);
+unsigned short icq_UpdateUserInfo(ICQLINK *link, const char *nick,
+     const char *first, const char *last, const char *email);
+unsigned short icq_UpdateAuthInfo(ICQLINK *link, unsigned long auth);
+unsigned short icq_UpdateMetaInfoSet(ICQLINK *link, const char *nick,
+     const char *first, const char *last, const char *email,
+     const char *email2, const char *email3, const char *city,
+     const char *state, const char *phone, const char *fax, const char *street,
+     const char *cellular, unsigned long zip, unsigned short cnt_code,
+     unsigned char cnt_stat, unsigned char emailhide);
+unsigned short icq_UpdateMetaInfoHomepage(ICQLINK *link, unsigned char age,
+     const char *homepage, unsigned char year, unsigned char month,
+     unsigned char day, unsigned char lang1, unsigned char lang2,
+     unsigned char lang3);
+unsigned short icq_UpdateMetaInfoAbout(ICQLINK *link, const char *about);
+unsigned short icq_UpdateMetaInfoSecurity(ICQLINK *link, unsigned char reqauth,
+     unsigned char webpresence, unsigned char pubip);
+unsigned short icq_UpdateNewUserInfo(ICQLINK *link, const char *nick,
+     const char *first, const char *last, const char *email);
+unsigned short icq_SendMetaInfoReq(ICQLINK *link, unsigned long uin);
+
+void icq_FmtLog(ICQLINK *link, int level, const char *fmt, ...);
+
+void icq_ContactAdd(ICQLINK *link, unsigned long cuin);
+void icq_ContactRemove(ICQLINK *link, unsigned long cuin);
+void icq_ContactClear(ICQLINK *link );
+void icq_ContactSetVis(ICQLINK *link, unsigned long cuin, unsigned char vu);
+
+/*** TCP ***/
+void icq_TCPMain(ICQLINK *link);
+
+void icq_TCPProcessReceived(ICQLINK *link);
+
+unsigned long icq_TCPSendMessage(ICQLINK *link, unsigned long uin,
+     const char *message);
+unsigned long icq_TCPSendURL(ICQLINK *link, unsigned long uin,
+     const char *message, const char *url);
+unsigned long icq_SendChatRequest(ICQLINK *link, unsigned long uin,
+     const char *message);
+void icq_AcceptChatRequest(ICQLINK *link, unsigned long uin, unsigned long seq);
+
+void icq_TCPSendChatData(ICQLINK *link, unsigned long uin, const char *data);
+void icq_TCPSendChatData_n(ICQLINK *link, unsigned long uin, const char *data, int len);
+void icq_TCPCloseChat(ICQLINK *link, unsigned long uin);
+
+void icq_CancelChatRequest(ICQLINK *link, unsigned long uin, 
+     unsigned long sequence);
+void icq_RefuseChatRequest(ICQLINK *link, unsigned long uin,
+     unsigned long sequence, const char *reason);
+
+/*** TCP ***/
+
+/* file session statuses- request receiver */
+#define FILE_STATUS_LISTENING    1
+#define FILE_STATUS_CONNECTED    3
+
+/* file session statuses- request sender */
+#define FILE_STATUS_CONNECTING   2
+
+#define FILE_STATUS_INITIALIZED  4
+#define FILE_STATUS_NEXT_FILE    5
+#define FILE_STATUS_STOP_FILE    6
+#define FILE_STATUS_NEW_SPEED    7
+
+/* once negotiation is complete, file session enters proper state */
+#define FILE_STATUS_READY        8
+#define FILE_STATUS_SENDING      8
+#define FILE_STATUS_RECEIVING    9  
+
+struct icq_TCPLink_s;
+
+typedef struct icq_FileSession_s {
+
+  unsigned long id;
+  int status;
+  ICQLINK *icqlink;
+  struct icq_TCPLink_s *tcplink;
+
+  int direction;
+
+  unsigned long remote_uin;
+  char remote_handle[64];
+
+  char **files;
+  int total_files;
+  int current_file_num;
+  unsigned long total_bytes;
+  unsigned long total_transferred_bytes;
+
+  char working_dir[512];
+  char current_file[64];
+  int current_fd;
+  unsigned long current_file_size;
+  unsigned long current_file_progress;
+
+  int current_speed;
+
+} icq_FileSession;
+          
+icq_FileSession *icq_AcceptFileRequest(ICQLINK *link, unsigned long uin,
+                 unsigned long sequence);
+unsigned long icq_SendFileRequest(ICQLINK *link, unsigned long uin,
+              const char *message, char **files);
+void icq_CancelFileRequest(ICQLINK *link, unsigned long uin, 
+     unsigned long sequence);
+void icq_RefuseFileRequest(ICQLINK *link, unsigned long uin,
+     unsigned long sequence, const char *reason);
+
+void icq_FileSessionSetSpeed(icq_FileSession *p, int speed);
+void icq_FileSessionClose(icq_FileSession *p);
+void icq_FileSessionSetWorkingDir(icq_FileSession *p, const char *dir);
+void icq_FileSessionSetFiles(icq_FileSession *p, char **files);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _ICQ_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/icqbyteorder.c	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,50 @@
+/*
+ * $Id: icqbyteorder.c 1162 2000-11-28 02:22:42Z warmenhoven $
+ *
+ * This header defines macros to handle ICQ protocol byte order conversion.
+ *
+ * Vadim Zaliva <lord@crocodile.org>
+ * http://www.crocodile.org/
+ * 
+ * Copyright (C) 1999 Vadim Zaliva
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/*
+ * I am really trying to use builtin optimized byte swap routines.
+ * they are highly optimised on some platforms.
+ * But as last resort this simple code is used.
+ */
+#ifndef HAVE_BYTESWAP_H
+# ifndef bswap_32
+unsigned long bswap_32(unsigned long v)
+{
+    unsigned char c,*x=(unsigned char *)&v;
+    c=x[0];x[0]=x[3];x[3]=c;
+    c=x[1];x[1]=x[2];x[2]=c;
+    return v;
+}
+# endif
+# ifndef bswap_16
+unsigned short bswap_16(unsigned short v)
+{
+    unsigned char c,*x=(unsigned char *)&v;
+    c=x[0];x[0]=x[1];x[1]=c;
+    return v;
+}
+# endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/icqbyteorder.h	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,116 @@
+/*
+ * $Id: icqbyteorder.h 1162 2000-11-28 02:22:42Z warmenhoven $
+ *
+ * This header defines macros to handle ICQ protocol byte order conversion.
+ *
+ * Vadim Zaliva <lord@crocodile.org>
+ * http://www.crocodile.org/
+ * 
+ * Copyright (C) 1999 Vadim Zaliva
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/*
+ * From ICQ protocol description:
+ * "Integers consisting of more than one byte is stored
+ * with the least significant byte first, and the most significant byte last
+ * (as is usual on the PC/Intel architecture)".
+ *
+ * whereas the network byte order, as used on the
+ * Internet, is Most Significant Byte first. (aka. Big Endian)
+ */
+
+#ifndef ICQ_BYTEORDER_H_FLAG
+#define ICQ_BYTEORDER_H_FLAG
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif         
+
+/* linux way */
+#ifdef HAVE_ENDIAN_H
+# include <endian.h> 
+#endif
+#ifdef HAVE_BYTESWAP_H
+# include <byteswap.h>
+#endif
+
+/* bsd way */
+#ifdef HAVE_MACHINE_ENDIAN_H
+# include <machine/endian.h>
+#endif
+
+/*
+ * Kind of portable way. this common header, at least I found it on BSD and Solaris.
+ * On Solaris this is only place where endiannes is defined.
+ */
+#ifdef HAVE_ARPA_NAMESER_COMPAT_H
+# include <arpa/nameser_compat.h>
+#endif
+
+/*
+ * I am really trying to use builtin optimized byte swap routines.
+ * they are highly optimised on some platforms.
+ * But as last resort this simple code is used.
+ */
+#ifndef HAVE_BYTESWAP_H
+# ifndef bswap_32
+extern unsigned long bswap_32(unsigned long v);
+# endif
+# ifndef bswap_16
+extern unsigned short bswap_16(unsigned short v);
+# endif
+#endif
+
+#ifdef BYTE_ORDER_LITTLE_ENDIAN
+# define htoicql(x)   (x)
+# define icqtohl(x)   (x)
+# define htoicqs(x)   (x)
+# define icqtohs(x)   (x)
+#else
+
+#ifndef BYTE_ORDER
+#   error "Unknown byte order!"
+#endif
+
+#if BYTE_ORDER == BIG_ENDIAN
+/* host is different from ICQ byte order */
+# define htoicql(x)   bswap_32(x)
+# define icqtohl(x)   bswap_32(x)
+# define htoicqs(x)   bswap_16(x)
+# define icqtohs(x)   bswap_16(x)
+#else
+# if BYTE_ORDER == LITTLE_ENDIAN
+/* host byte order match ICQ byte order */
+#   define htoicql(x)   (x)
+#   define icqtohl(x)   (x)
+#   define htoicqs(x)   (x)
+#   define icqtohs(x)   (x)
+# else
+#   error "Unsupported byte order!"
+# endif
+#endif
+
+#endif
+
+/* ICQ byte order is always different from network byte order. */
+# define ntoicql(x)   bswap_32(x)
+# define icqtonl(x)   bswap_32(x)
+# define ntoicqs(x)   bswap_16(x)
+# define icqtons(x)   bswap_16(x)
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/icqlib.c	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,621 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+$Id: icqlib.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Log$
+Revision 1.1  2000/11/28 02:22:42  warmenhoven
+icq. whoop de doo
+
+Revision 1.44  2000/07/24 03:10:08  bills
+added support for real nickname during TCP transactions like file and
+chat, instead of using Bill all the time (hmm, where'd I get that from? :)
+
+Revision 1.43  2000/07/09 22:05:11  bills
+removed unnecessary functions
+
+Revision 1.42  2000/07/09 18:28:07  denis
+Initial memset() in icq_Init() replaced by callback's clearance.
+
+Revision 1.41  2000/06/15 01:50:39  bills
+removed *Seq functions
+
+Revision 1.40  2000/05/10 19:06:59  denis
+UDP outgoing packet queue was implemented.
+
+Revision 1.39  2000/05/03 18:12:36  denis
+Unfinished UDP queue was commented out.
+
+Revision 1.38  2000/04/10 16:36:04  denis
+Some more Win32 compatibility from Guillaume Rosanis <grs@mail.com>
+
+Revision 1.37  2000/04/06 16:38:04  denis
+icq_*Send*Seq() functions with specified sequence number were added.
+
+Revision 1.36  2000/04/05 14:37:02  denis
+Applied patch from "Guillaume R." <grs@mail.com> for basic Win32
+compatibility.
+
+Revision 1.35  2000/01/16 03:59:10  bills
+reworked list code so list_nodes don't need to be inside item structures,
+removed strlist code and replaced with generic list calls
+
+Revision 1.34  1999/12/27 16:06:32  bills
+cleanups
+
+Revision 1.33  1999/10/03 21:35:55  tim
+Fixed "url" and "descr" parameters order when sending a URL via TCP.
+
+Revision 1.32  1999/09/29 16:49:43  denis
+Host/network/icq byteorder systemized.
+icq_Init() cleaned up.
+
+Revision 1.31  1999/07/18 20:15:55  bills
+changed to use new byte-order functions & contact list functions
+
+Revision 1.30  1999/07/16 12:27:06  denis
+Other global variables moved to ICQLINK structure.
+Initialization of random number generator added in icq_Init()
+Cleaned up.
+
+Revision 1.29  1999/07/12 15:13:31  cproch
+- added definition of ICQLINK to hold session-specific global variabled
+  applications which have more than one connection are now possible
+- changed nearly every function defintion to support ICQLINK parameter
+
+Revision 1.28  1999/07/03 02:26:02  bills
+added new code to support thruSrv arg to SendMessage and SendURL
+
+Revision 1.27  1999/04/17 19:21:37  bills
+modified Send* Functions to return DWORD instead of WORD
+
+Revision 1.26  1999/04/14 14:48:18  denis
+Switched from icq_Log callback to icq_Fmt function.
+Cleanups for "strict" compiling (-ansi -pedantic)
+
+Revision 1.25  1999/04/05 13:14:57  denis
+Send messages and URLs to 'not in list' users fixed.
+
+Revision 1.24  1999/03/31 01:43:40  bills
+added TCP support to SendURL
+
+Revision 1.23  1999/03/30 22:47:44  lord
+list of countries now sorted.
+
+Revision 1.22  1999/03/28 03:18:22  bills
+enable tcp messaging in icq_SendMessage, uncommented icq_OurPort and
+icq_OurIp and fixed function names so icqlib compiles
+
+Revision 1.21  1999/03/25 22:16:43  bills
+added #include "util.h"
+
+Revision 1.20  1999/03/24 11:37:36  denis
+Underscored files with TCP stuff renamed.
+TCP stuff cleaned up
+Function names changed to corresponding names.
+icqlib.c splitted to many small files by subject.
+C++ comments changed to ANSI C comments.
+
+Revision 1.19  1999/03/22 20:51:28  bills
+added code in icq_HandleUserOnline to set/clear new struct entries in
+icq_ContactItem; added cleanup code in icq_HandleUserOffline for same
+
+Revision 1.18  1999/03/09 13:14:05  denis
+Cyrillic recoding removed from URLs
+
+Revision 1.17  1999/03/05 13:57:54  denis
+Some cosmetic changes...
+
+Revision 1.16  1998/12/08 16:00:59  denis
+Cleaned up a little before releasing
+
+Revision 1.15  1998/11/25 19:18:16  denis
+Added close icq_ProxySok in icq_Disconnect
+
+Revision 1.14  1998/11/25 09:48:49  denis
+icq_GetProxySok and icq_HandleProxyResponse methods added
+Connection terminated support added
+
+Revision 1.13  1998/11/19 12:22:48  denis
+SOCKS support cleaned a little
+icq_RecvUrl renamed to icq_RecvURL
+icq_ProxyAuth added for Username/Password Authentication
+URL/Description order inverted
+icq_Quit splitted to icq_Logout and icq_Disconnect
+icq_ProxyName and icq_ProxyPass range checking added
+
+Revision 1.12  1998/11/18 16:21:29  denis
+Fixed SOCKS5 proxy support
+
+ */
+
+#include "icqlib.h"
+
+#include <stdlib.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#include <time.h>
+
+#ifdef _WIN32
+#include <winsock.h>
+#else
+#include <netdb.h>
+#include <sys/socket.h>
+#endif
+
+#include <sys/stat.h>
+
+#ifndef _WIN32
+#include <sys/time.h>
+#include <netinet/in.h>
+#endif
+
+#include "util.h"
+#include "icqtypes.h"
+#include "icq.h"
+#include "udp.h"
+#include "tcp.h"
+#include "queue.h"
+
+int icq_Russian = FALSE;
+BYTE icq_LogLevel = 0;
+
+DWORD icq_SendMessage(ICQLINK *link, DWORD uin, const char *text, BYTE thruSrv)
+{
+  if(thruSrv==ICQ_SEND_THRUSERVER)
+    return icq_UDPSendMessage(link, uin, text);
+  else if(thruSrv==ICQ_SEND_DIRECT)
+    return icq_TCPSendMessage(link, uin, text);
+  else if(thruSrv==ICQ_SEND_BESTWAY)
+  {
+    icq_ContactItem *pcontact=icq_ContactFind(link, uin);
+    if(pcontact)
+    {
+      if(pcontact->tcp_flag == 0x04)
+        return icq_TCPSendMessage(link, uin, text);
+      else
+        return icq_UDPSendMessage(link, uin, text);
+    }
+    else
+    {
+      return icq_UDPSendMessage(link, uin, text);
+    }
+  }
+  return 0;
+}
+
+DWORD icq_SendURL(ICQLINK *link, DWORD uin, const char *url, const char *descr, BYTE thruSrv)
+{
+  if(thruSrv==ICQ_SEND_THRUSERVER)
+    return icq_UDPSendURL(link, uin, url, descr);
+  else if(thruSrv==ICQ_SEND_DIRECT)
+    return icq_TCPSendURL(link, uin, descr, url);
+  else if(thruSrv==ICQ_SEND_BESTWAY)
+  {
+    icq_ContactItem *pcontact=icq_ContactFind(link, uin);
+    if(pcontact)
+    {
+      if(pcontact->tcp_flag == 0x04)
+        return icq_TCPSendURL(link, uin, descr, url);
+      else
+        return icq_UDPSendURL(link, uin, url, descr);
+    }
+    else
+    {
+      return icq_UDPSendURL(link, uin, url, descr);
+    }
+  }
+  return 0;
+}
+
+void icq_Init(ICQLINK *link, DWORD uin, const char *password,
+  const char *nick)
+{
+  srand(time(0L));
+/*   memset(link, 0, sizeof(ICQLINK)); */
+
+  /* Initialize all callbacks */
+  link->icq_Logged = 0L;
+  link->icq_Disconnected = 0L;
+  link->icq_RecvMessage = 0L;
+  link->icq_RecvURL = 0L;
+  link->icq_RecvWebPager = 0L;
+  link->icq_RecvMailExpress = 0L;
+  link->icq_RecvChatReq = 0L;
+  link->icq_RecvFileReq = 0L;
+  link->icq_RecvAdded = 0L;
+  link->icq_RecvAuthReq = 0L;
+  link->icq_UserFound = 0L;
+  link->icq_SearchDone = 0L;
+  link->icq_UserOnline = 0L;
+  link->icq_UserOffline = 0L;
+  link->icq_UserStatusUpdate = 0L;
+  link->icq_InfoReply = 0L;
+  link->icq_ExtInfoReply = 0L;
+  link->icq_WrongPassword = 0L;
+  link->icq_InvalidUIN = 0L;
+  link->icq_Log = 0L;
+  link->icq_SrvAck = 0L;
+  link->icq_RequestNotify = 0L;
+  link->icq_NewUIN = 0L;
+  link->icq_SetTimeout = 0L;
+  link->icq_MetaUserFound = 0L;
+  link->icq_MetaUserInfo = 0L;
+  link->icq_MetaUserWork = 0L;
+  link->icq_MetaUserMore = 0L;
+  link->icq_MetaUserAbout = 0L;
+  link->icq_MetaUserInterests = 0L;
+  link->icq_MetaUserAffiliations = 0L;
+  link->icq_MetaUserHomePageCategory = 0L;
+
+  /* General stuff */
+  link->icq_Uin = uin;
+  link->icq_Password = strdup(password);
+  link->icq_Nick = strdup(nick);
+  link->icq_OurIP = -1;
+  link->icq_OurPort = 0;
+  link->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;
+  icq_UDPQueueNew(link);
+
+  icq_TCPInit(link);
+
+  /* Proxy stuff */
+  link->icq_UseProxy = 0;
+  link->icq_ProxyHost = 0L;
+  link->icq_ProxyIP = -1;
+  link->icq_ProxyPort = 0;
+  link->icq_ProxyAuth = 0;
+  link->icq_ProxyName = 0L;
+  link->icq_ProxyPass = 0L;
+  link->icq_ProxySok = -1;
+  link->icq_ProxyOurPort = 0;
+  link->icq_ProxyDestIP = -1;
+  link->icq_ProxyDestPort = 0;
+}
+
+void icq_Done(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);
+  icq_UDPQueueDelete(link);
+}
+
+/******************************
+Main function connects gets icq_Uin
+and icq_Password and logins in and sits
+in a loop waiting for server responses.
+*******************************/
+void icq_Main(ICQLINK *link)
+{
+  struct timeval tv;
+  fd_set readfds;
+
+  tv.tv_sec = 0;
+  tv.tv_usec = 0;
+  FD_ZERO(&readfds);
+  FD_SET(link->icq_UDPSok, &readfds);
+  select(link->icq_UDPSok+1, &readfds, 0L, 0L, &tv);
+  if(FD_ISSET(link->icq_UDPSok, &readfds))
+    icq_HandleServerResponse(link);
+  icq_TCPMain(link);
+}
+
+/**********************************
+Connects to hostname on port port
+hostname can be DNS or nnn.nnn.nnn.nnn
+write out messages to the FD aux
+***********************************/
+int icq_Connect(ICQLINK *link, const char *hostname, int port)
+{
+  char buf[1024]; /*, un = 1;*/
+/*  char tmpbuf[256], our_host[256]*/
+  int conct, res;
+  unsigned int length;
+  struct sockaddr_in sin, prsin;  /* used to store inet addr stuff */
+  struct hostent *host_struct; /* used in DNS llokup */
+
+  link->icq_UDPSok = socket(AF_INET, SOCK_DGRAM, 0);/* create the unconnected socket*/
+  if(link->icq_UDPSok == -1)
+  {
+    icq_FmtLog(link, ICQ_LOG_FATAL, "Socket creation failed\n");
+    return -1;
+  }
+  icq_FmtLog(link, ICQ_LOG_MESSAGE, "Socket created attempting to connect\n");
+  sin.sin_addr.s_addr = INADDR_ANY;
+  sin.sin_family = AF_INET; /* we're using the inet not appletalk*/
+  sin.sin_port = 0;
+  if(bind(link->icq_UDPSok, (struct sockaddr*)&sin, sizeof(struct sockaddr))<0)
+  {
+    icq_FmtLog(link, ICQ_LOG_FATAL, "Can't bind socket to free port\n");
+    return -1;
+  }
+  length = sizeof(sin);
+  getsockname(link->icq_UDPSok, (struct sockaddr*)&sin, &length);
+  link->icq_ProxyOurPort = ntohs(sin.sin_port);
+  if(link->icq_UseProxy)
+  {
+    icq_FmtLog(link, ICQ_LOG_MESSAGE, "[SOCKS] Trying to use SOCKS5 proxy\n");
+    prsin.sin_addr.s_addr = inet_addr(link->icq_ProxyHost);
+    if(prsin.sin_addr.s_addr  == (unsigned long)-1) /* name isn't n.n.n.n so must be DNS */
+    {
+      host_struct = gethostbyname(link->icq_ProxyHost);
+      if(host_struct == 0L)
+      {
+        icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Can't find hostname: %s\n", link->icq_ProxyHost);
+        return -1;
+      }
+      prsin.sin_addr = *((struct in_addr*)host_struct->h_addr);
+    }
+    link->icq_ProxyIP = ntohl(prsin.sin_addr.s_addr);
+    prsin.sin_family = AF_INET; /* we're using the inet not appletalk*/
+    prsin.sin_port = htons(link->icq_ProxyPort); /* port */
+    link->icq_ProxySok = socket(AF_INET, SOCK_STREAM, 0);/* create the unconnected socket*/
+    if(link->icq_ProxySok == -1)
+    {
+      icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Socket creation failed\n");
+      return -1;
+    }
+    icq_FmtLog(link, ICQ_LOG_MESSAGE, "[SOCKS] Socket created attempting to connect\n");
+    conct = connect(link->icq_ProxySok, (struct sockaddr *) &prsin, sizeof(prsin));
+    if(conct == -1) /* did we connect ?*/
+    {
+      icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Connection refused\n");
+      return -1;
+    }
+    buf[0] = 5; /* protocol version */
+    buf[1] = 1; /* number of methods */
+    if(!strlen(link->icq_ProxyName) || !strlen(link->icq_ProxyPass) || !link->icq_ProxyAuth)
+      buf[2] = 0; /* no authorization required */
+    else
+      buf[2] = 2; /* method username/password */
+#ifdef _WIN32
+    send(link->icq_ProxySok, buf, 3, 0);
+    res = recv(link->icq_ProxySok, buf, 2, 0);
+#else
+    write(link->icq_ProxySok, buf, 3);
+    res = read(link->icq_ProxySok, buf, 2);
+#endif
+    if(strlen(link->icq_ProxyName) && strlen(link->icq_ProxyPass) && link->icq_ProxyAuth)
+    {
+      if(res != 2 || buf[0] != 5 || buf[1] != 2) /* username/password authentication*/
+      {
+        icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Authentication method incorrect\n");
+#ifdef _WIN32
+        closesocket(link->icq_ProxySok);
+#else
+        close(link->icq_ProxySok);
+#endif
+        return -1;
+      }
+      buf[0] = 1; /* version of subnegotiation */
+      buf[1] = strlen(link->icq_ProxyName);
+      memcpy(&buf[2], link->icq_ProxyName, buf[1]);
+      buf[2+buf[1]] = strlen(link->icq_ProxyPass);
+      memcpy(&buf[3+buf[1]], link->icq_ProxyPass, buf[2+buf[1]]);
+#ifdef _WIN32
+      send(link->icq_ProxySok, buf, buf[1]+buf[2+buf[1]]+3, 0);
+      res = recv(link->icq_ProxySok, buf, 2, 0);
+#else
+      write(link->icq_ProxySok, buf, buf[1]+buf[2+buf[1]]+3);
+      res = read(link->icq_ProxySok, buf, 2);
+#endif
+      if(res != 2 || buf[0] != 1 || buf[1] != 0)
+      {
+        icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Authorization failure\n");
+#ifdef _WIN32
+        closesocket(link->icq_ProxySok);
+#else
+        close(link->icq_ProxySok);
+#endif
+        return -1;
+      }
+    }
+    else
+    {
+      if(res != 2 || buf[0] != 5 || buf[1] != 0) /* no authentication required */
+      {
+        icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Authentication method incorrect\n");
+#ifdef _WIN32
+        closesocket(link->icq_ProxySok);
+#else
+        close(link->icq_ProxySok);
+#endif
+        return -1;
+      }
+    }
+    buf[0] = 5; /* protocol version */
+    buf[1] = 3; /* command UDP associate */
+    buf[2] = 0; /* reserved */
+    buf[3] = 1; /* address type IP v4 */
+    buf[4] = (char)0;
+    buf[5] = (char)0;
+    buf[6] = (char)0;
+    buf[7] = (char)0;
+    *(unsigned short*)&buf[8] = htons(link->icq_ProxyOurPort);
+/*     memcpy(&buf[8], &link->icq_ProxyOurPort, 2); */
+#ifdef _WIN32
+    send(link->icq_ProxySok, buf, 10, 0);
+    res = recv(link->icq_ProxySok, buf, 10, 0);
+#else
+    write(link->icq_ProxySok, buf, 10);
+    res = read(link->icq_ProxySok, buf, 10);
+#endif
+    if(res != 10 || buf[0] != 5 || buf[1] != 0)
+    {
+      switch(buf[1])
+      {
+        case 1:
+          icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] General SOCKS server failure\n");
+          break;
+        case 2:
+          icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Connection not allowed by ruleset\n");
+          break;
+        case 3:
+          icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Network unreachable\n");
+          break;
+        case 4:
+          icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Host unreachable\n");
+          break;
+        case 5:
+          icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Connection refused\n");
+          break;
+        case 6:
+          icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] TTL expired\n");
+          break;
+        case 7:
+          icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Command not supported\n");
+          break;
+        case 8:
+          icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Address type not supported\n");
+          break;
+        default:
+          icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Unknown SOCKS server failure\n");
+          break;
+      }
+#ifdef _WIN32
+      closesocket(link->icq_ProxySok);
+#else
+      close(link->icq_ProxySok);
+#endif
+      return -1;
+    }
+  }
+  sin.sin_addr.s_addr = inet_addr(hostname); /* checks for n.n.n.n notation */
+  if(sin.sin_addr.s_addr == (unsigned long)-1) /* name isn't n.n.n.n so must be DNS */
+  {
+    host_struct = gethostbyname(hostname);
+    if(host_struct == 0L)
+    {
+      icq_FmtLog(link, ICQ_LOG_FATAL, "Can't find hostname: %s\n", hostname);
+      if(link->icq_UseProxy)
+      {
+#ifdef _WIN32
+        closesocket(link->icq_ProxySok);
+#else
+        close(link->icq_ProxySok);
+#endif
+      }
+      return -1;
+    }
+    sin.sin_addr = *((struct in_addr *)host_struct->h_addr);
+  }
+  if(link->icq_UseProxy)
+  {
+    link->icq_ProxyDestIP = ntohl(sin.sin_addr.s_addr);
+    memcpy(&sin.sin_addr.s_addr, &buf[4], 4);
+  }
+  sin.sin_family = AF_INET; /* we're using the inet not appletalk*/
+  sin.sin_port = htons(port); /* port */
+  if(link->icq_UseProxy)
+  {
+    link->icq_ProxyDestPort = port;
+    memcpy(&sin.sin_port, &buf[8], 2);
+  }
+  conct = connect(link->icq_UDPSok, (struct sockaddr*)&sin, sizeof(sin));
+  if(conct == -1) /* did we connect ?*/
+  {
+    icq_FmtLog(link, ICQ_LOG_FATAL, "Connection refused\n");
+    if(link->icq_UseProxy)
+    {
+#ifdef _WIN32
+      closesocket(link->icq_ProxySok);
+#else
+      close(link->icq_ProxySok);
+#endif
+    }
+    return -1;
+  }
+  length = sizeof(sin) ;
+  getsockname(link->icq_UDPSok, (struct sockaddr*)&sin, &length);
+  link->icq_OurIP = ntohl(sin.sin_addr.s_addr);
+  link->icq_OurPort = ntohs(sin.sin_port);
+  return link->icq_UDPSok;
+}
+
+void icq_Disconnect(ICQLINK *link)
+{
+#ifdef _WIN32
+  closesocket(link->icq_UDPSok);
+#else
+  close(link->icq_UDPSok);
+#endif
+  if(link->icq_UseProxy)
+  {
+#ifdef _WIN32
+    closesocket(link->icq_ProxySok);
+#else
+    close(link->icq_ProxySok);
+#endif
+  }
+  icq_UDPQueueFree(link);
+}
+
+/*
+void icq_InitNewUser(const char *hostname, DWORD port)
+{
+  srv_net_icq_pak pak;
+  int s;
+  struct timeval tv;
+  fd_set readfds;
+
+  icq_Connect(hostname, port);
+  if((icq_UDPSok == -1) || (icq_UDPSok == 0))
+  {
+    printf("Couldn't establish connection\n");
+    exit(1);
+  }
+  icq_RegNewUser(icq_Password);
+  for(;;)
+  {
+    tv.tv_sec = 2;
+    tv.tv_usec = 500000;
+
+    FD_ZERO(&readfds);
+    FD_SET(icq_UDPSok, &readfds);
+
+    select(icq_UDPSok+1, &readfds, 0L, 0L, &tv);
+
+    if(FD_ISSET(icq_UDPSok, &readfds))
+    {
+      s = icq_UDPSockRead(icq_UDPSok, &pak.head, sizeof(pak));
+      if(icqtohs(pak.head.cmd) == SRV_NEW_UIN)
+      {
+        icq_Uin = icqtohl(&pak.data[2]);
+        return;
+      }
+    }
+  }
+}
+*/
+
+/************************
+icq_UDPServMess functions
+*************************/
+BOOL icq_GetServMess(ICQLINK *link, WORD num)
+{
+  return ((link->icq_UDPServMess[num/8] & (1 << (num%8))) >> (num%8));
+}
+
+void icq_SetServMess(ICQLINK *link, WORD num)
+{
+  link->icq_UDPServMess[num/8] |= (1 << (num%8));
+}
+
+int icq_GetSok(ICQLINK *link)
+{
+  return link->icq_UDPSok;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/icqlib.h	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,45 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+#ifndef _ICQLIB_H_
+#define _ICQLIB_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* for strdup(), bzero() and snprintf() declarations */
+#ifndef __USE_BSD
+#define __USE_BSD 1
+#define __need_bsd_undef 1
+#endif
+#include <string.h>
+#include <stdio.h>
+#ifdef __need_bsd_undef
+#undef __USE_BSD
+#endif
+
+#include <sys/types.h>
+
+#include "util.h"
+#include "contacts.h"
+
+BOOL icq_GetServMess(ICQLINK *link, WORD num);
+void icq_SetServMess(ICQLINK *link, WORD num);
+void icq_RusConv(const char to[4], char *t_in);
+void icq_RusConv_n(const char to[4], char *t_in, int len);
+
+#ifndef _WIN32
+#ifndef inet_addr
+extern unsigned long inet_addr(const char *cp);
+#endif /* inet_addr */
+#ifndef inet_aton
+extern int inet_aton(const char *cp, struct in_addr *inp);
+#endif /* inet_aton */
+#ifndef inet_ntoa
+extern char *inet_ntoa(struct in_addr in);
+#endif /* inet_ntoa */
+#ifndef strdup
+extern char *strdup(const char *s);
+#endif /* strdup */
+#endif /* _WIN32 */
+
+#endif /* _ICQLIB_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/icqpacket.c	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,387 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+$Id: icqpacket.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Log$
+Revision 1.1  2000/11/28 02:22:42  warmenhoven
+icq. whoop de doo
+
+Revision 1.10  2000/07/07 15:26:35  denis
+"icq_Packet data overflow" log message temporarily commented out.
+
+Revision 1.9  2000/06/25 16:26:36  denis
+icq_PacketUDPDump() tweaked a little.
+
+Revision 1.8  2000/05/03 18:20:40  denis
+icq_PacketReadUDPInUIN() was added.
+
+Revision 1.7  2000/04/05 14:37:02  denis
+Applied patch from "Guillaume R." <grs@mail.com> for basic Win32
+compatibility.
+
+Revision 1.6  2000/01/16 03:59:10  bills
+reworked list code so list_nodes don't need to be inside item structures,
+removed strlist code and replaced with generic list calls
+
+Revision 1.5  1999/09/29 19:58:20  bills
+cleanup
+
+Revision 1.4  1999/09/29 16:56:10  denis
+Cleanups.
+
+Revision 1.3  1999/07/18 20:18:43  bills
+changed to use new byte-order functions
+
+Revision 1.2  1999/07/16 15:45:05  denis
+Cleaned up.
+
+Revision 1.1  1999/07/16 12:11:36  denis
+UDP packet support added.
+tcp_packet* functions renamed to icq_Packet*
+
+Revision 1.8  1999/07/12 15:13:38  cproch
+- added definition of ICQLINK to hold session-specific global variabled
+  applications which have more than one connection are now possible
+- changed nearly every function defintion to support ICQLINK parameter
+
+Revision 1.7  1999/07/03 06:33:52  lord
+. byte order conversion macros added
+. some compilation warnings removed
+
+Revision 1.6  1999/04/17 19:36:50  bills
+added tcp_packet_node_delete function and changed structure to include
+list_node for new list routines.
+
+Revision 1.5  1999/04/14 15:08:04  denis
+Cleanups for "strict" compiling (-ansi -pedantic)
+
+*/
+
+/*
+ * ICQ packet abstraction
+ */
+
+#include <stdlib.h>
+#include <sys/types.h>
+
+#ifdef _WIN32
+#include <winsock.h>
+#else
+#include <sys/socket.h>
+#endif
+
+#include "icqtypes.h"
+#include "icq.h"
+#include "icqlib.h"
+#include "icqpacket.h"
+#include "tcp.h"
+#include "util.h"
+#include "icqbyteorder.h"
+#include "list.h"
+
+icq_Packet *icq_PacketNew()
+{
+  icq_Packet *p=(icq_Packet*)malloc(sizeof(icq_Packet));
+
+  p->length=0;
+  p->cursor=0;
+  p->id=0;
+
+  return p;
+}
+
+void icq_PacketDelete(void *p)
+{
+  free(p);
+}
+
+void icq_PacketAppend32(icq_Packet *p, DWORD i)
+{
+  DWORD val=i;
+
+  *(unsigned long*)((p->data)+(p->cursor))=htoicql(val);
+  icq_PacketAdvance(p, sizeof(DWORD));
+}
+
+void icq_PacketAppend32n(icq_Packet *p, DWORD i)
+{
+  DWORD val=i;
+
+  *(DWORD *)((p->data)+(p->cursor)) = val;
+  icq_PacketAdvance(p, sizeof(DWORD));
+}
+
+DWORD icq_PacketRead32(icq_Packet *p)
+{
+  DWORD val;
+
+  val = icqtohl(*(DWORD *)((p->data)+(p->cursor)));
+  icq_PacketAdvance(p, sizeof(DWORD));
+
+  return val;
+}
+
+DWORD icq_PacketRead32n(icq_Packet *p)
+{
+  DWORD val;
+
+  val = *(DWORD*)((p->data)+(p->cursor));
+  icq_PacketAdvance(p, sizeof(DWORD));
+
+  return val;
+}
+
+void icq_PacketAppend16(icq_Packet *p, WORD i)
+{
+  WORD val=i;
+
+  *(WORD *)((p->data)+(p->cursor)) = htoicqs(val);
+  icq_PacketAdvance(p, sizeof(WORD));
+}
+
+void icq_PacketAppend16n(icq_Packet *p, WORD i)
+{
+  WORD val=i;
+
+  *(WORD *)((p->data)+(p->cursor)) = val;
+  icq_PacketAdvance(p, sizeof(WORD));
+}
+
+WORD icq_PacketRead16(icq_Packet *p)
+{
+  WORD val;
+
+  val = icqtohs(*(WORD *)((p->data)+(p->cursor)));
+  icq_PacketAdvance(p, sizeof(WORD));
+
+  return val;
+}
+
+WORD icq_PacketRead16n(icq_Packet *p)
+{
+  WORD val;
+
+  val = *(WORD*)((p->data)+(p->cursor));
+  icq_PacketAdvance(p, sizeof(WORD));
+
+  return val;
+}
+
+void icq_PacketAppend8(icq_Packet *p, BYTE i)
+{
+  BYTE val=i;
+
+  memcpy((p->data)+(p->cursor), &val, sizeof(BYTE));
+  icq_PacketAdvance(p, sizeof(BYTE));
+}
+
+BYTE icq_PacketRead8(icq_Packet *p)
+{
+  BYTE val;
+
+  memcpy(&val, (p->data)+(p->cursor), sizeof(BYTE));
+  icq_PacketAdvance(p, sizeof(BYTE));
+
+  return val;
+}
+
+void icq_PacketAppendString(icq_Packet *p, const char *s)
+{
+  if(s)
+  {
+    int length=strlen(s)+1;
+
+    icq_PacketAppend16(p, length);
+    icq_PacketAppend(p, s, length);
+  }
+  else
+  {
+    icq_PacketAppend16(p, 1);
+    icq_PacketAppend8(p,0);
+  }
+}
+
+const char *icq_PacketReadString(icq_Packet *p)
+{
+  int length=icq_PacketRead16(p);
+
+  return (const char *)icq_PacketRead(p, length);
+}
+
+char *icq_PacketReadStringNew(icq_Packet *p)
+{
+  char *ptr;
+  int length=icq_PacketRead16(p);
+
+  ptr = (char*)malloc(length);
+  if(!ptr)
+    return 0L;
+  strncpy(ptr, icq_PacketRead(p, length), length);
+  return ptr;
+}
+
+void icq_PacketAppendStringFE(icq_Packet *p, const char *s)
+{
+  if(s)
+  {
+    int length=strlen(s);
+    icq_PacketAppend(p, s, length);
+  }
+  icq_PacketAppend8(p, 0xFE);
+}
+
+void icq_PacketAppendString0(icq_Packet *p, const char *s)
+{
+  if(s)
+  {
+    int length=strlen(s);
+    icq_PacketAppend(p, s, length);
+  }
+  icq_PacketAppend8(p, 0);
+}
+
+WORD icq_PacketReadUDPOutVer(icq_Packet *p)
+{
+  icq_PacketGoto(p, 0);
+  return icq_PacketRead16(p);
+}
+
+WORD icq_PacketReadUDPOutCmd(icq_Packet *p)
+{
+  icq_PacketGoto(p, 14 /*2*/);
+  return icq_PacketRead16(p);
+}
+
+WORD icq_PacketReadUDPOutSeq1(icq_Packet *p)
+{
+  icq_PacketGoto(p, 16);
+  return icq_PacketRead16(p);
+}
+
+WORD icq_PacketReadUDPOutSeq2(icq_Packet *p)
+{
+  icq_PacketGoto(p, 18 /*4*/);
+  return icq_PacketRead16(p);
+}
+
+WORD icq_PacketReadUDPInVer(icq_Packet *p)
+{
+  icq_PacketGoto(p, 0);
+  return icq_PacketRead16(p);
+}
+
+WORD icq_PacketReadUDPInCmd(icq_Packet *p)
+{
+  icq_PacketGoto(p, 7);
+  return icq_PacketRead16(p);
+}
+
+WORD icq_PacketReadUDPInSeq1(icq_Packet *p)
+{
+  icq_PacketGoto(p, 9);
+  return icq_PacketRead16(p);
+}
+
+WORD icq_PacketReadUDPInSeq2(icq_Packet *p)
+{
+  icq_PacketGoto(p, 11);
+  return icq_PacketRead16(p);
+}
+
+DWORD icq_PacketReadUDPInUIN(icq_Packet *p)
+{
+  icq_PacketGoto(p, 13);
+  return icq_PacketRead32(p);
+}
+
+void icq_PacketAppend(icq_Packet *p, const void *data, int length)
+{
+  memcpy((p->data)+(p->cursor), data, length);
+  icq_PacketAdvance(p, length);
+}
+
+const void *icq_PacketRead(icq_Packet *p, int length)
+{
+  const void *data=(p->data)+(p->cursor);
+
+  icq_PacketAdvance(p, length);
+
+  return data;
+}
+
+void icq_PacketShortDump(icq_Packet *p)
+{
+  printf("icq_Packet %x { id=%d, cursor=%x, length=%d }\n", 
+         (int)p, (int)p->id, p->cursor, p->length);
+}
+
+void icq_PacketDump(icq_Packet *p)
+{
+  icq_PacketShortDump(p);
+  hex_dump((char*)&(p->length), p->length+sizeof(WORD));
+}
+
+void icq_PacketUDPDump(icq_Packet *p)
+{
+  icq_PacketShortDump(p);
+  hex_dump((char*)&(p->data), p->length);
+}
+
+void icq_PacketBegin(icq_Packet *p)
+{
+  p->cursor=0;
+}
+
+void icq_PacketEnd(icq_Packet *p)
+{
+  p->cursor=p->length;
+}
+
+void icq_PacketAdvance(icq_Packet *p, int i)
+{
+  p->cursor+=i;
+
+  if(p->cursor > p->length)
+    p->length=p->cursor;
+
+/* Do nothing, because we don't have ICQLINK here */
+/*   if(p->cursor > ICQ_PACKET_DATA_SIZE) */
+/*     icq_FmtLog(0L, ICQ_LOG_WARNING, "icq_Packet data overflow\n"); */
+}
+
+void icq_PacketGoto(icq_Packet *p, int i)
+{
+  icq_PacketBegin(p);
+  icq_PacketAdvance(p, i);
+}
+
+void icq_PacketGotoUDPOutData(icq_Packet *p, int i)
+{
+  /* Go to data in UDP _client_ packet. */
+  icq_PacketGoto(p, 24+i);
+}
+
+void icq_PacketGotoUDPInData(icq_Packet *p, int i)
+{
+  /* Go to data in UDP _server_ packet. */
+  icq_PacketGoto(p, 21+i);
+}
+
+WORD icq_PacketPos(icq_Packet *p)
+{
+  return p->cursor;
+}
+
+int icq_PacketSend(icq_Packet *p, int socket)
+{
+  int result;
+
+  result=send(socket, (const char*)&(p->length), p->length+sizeof(WORD), 0);
+
+#ifdef TCP_RAW_TRACE
+  printf("%d bytes sent on socket %d, result %d\n", 
+    p->length+1, socket, result);
+  icq_PacketDump(p);
+#endif /* TCP_RAW_TRACE */
+
+  return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/icqpacket.h	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+#ifndef _ICQ_PACKET_H_
+#define _ICQ_PACKET_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "icqtypes.h"
+
+#define ICQ_PACKET_DATA_SIZE   4096
+
+typedef struct icq_Packet_s
+{
+  DWORD id;
+  WORD cursor;
+  WORD length;
+  BYTE data[ICQ_PACKET_DATA_SIZE];
+} icq_Packet;
+
+icq_Packet *icq_PacketNew();
+void icq_PacketDelete(void *);
+
+void icq_PacketAppend(icq_Packet *, const void *, int);
+void icq_PacketAppend32(icq_Packet *, DWORD);
+void icq_PacketAppend32n(icq_Packet *, DWORD);
+void icq_PacketAppend16(icq_Packet *, WORD);
+void icq_PacketAppend16n(icq_Packet *, WORD);
+void icq_PacketAppend8(icq_Packet *, BYTE);
+void icq_PacketAppendString(icq_Packet *, const char *);
+void icq_PacketAppendStringFE(icq_Packet *, const char *);
+void icq_PacketAppendString0(icq_Packet *, const char *);
+
+const void *icq_PacketRead(icq_Packet*, int);
+DWORD icq_PacketRead32(icq_Packet*);
+DWORD icq_PacketRead32n(icq_Packet*);
+WORD icq_PacketRead16(icq_Packet*);
+WORD icq_PacketRead16n(icq_Packet*);
+BYTE icq_PacketRead8(icq_Packet*);
+const char *icq_PacketReadString(icq_Packet*);
+char *icq_PacketReadStringNew(icq_Packet*);
+WORD icq_PacketReadUDPOutVer(icq_Packet*);
+WORD icq_PacketReadUDPOutCmd(icq_Packet*);
+WORD icq_PacketReadUDPOutSeq1(icq_Packet*);
+WORD icq_PacketReadUDPOutSeq2(icq_Packet*);
+WORD icq_PacketReadUDPInVer(icq_Packet*);
+WORD icq_PacketReadUDPInCmd(icq_Packet*);
+WORD icq_PacketReadUDPInSeq1(icq_Packet*);
+WORD icq_PacketReadUDPInSeq2(icq_Packet*);
+DWORD icq_PacketReadUDPInUIN(icq_Packet*);
+
+void icq_PacketDump(icq_Packet*);
+void icq_PacketUDPDump(icq_Packet*);
+void icq_PacketBegin(icq_Packet*);
+void icq_PacketEnd(icq_Packet*);
+void icq_PacketAdvance(icq_Packet*, int);
+void icq_PacketGoto(icq_Packet*, int);
+void icq_PacketGotoUDPOutData(icq_Packet*, int);
+void icq_PacketGotoUDPInData(icq_Packet*, int);
+WORD icq_PacketPos(icq_Packet*);
+int icq_PacketSend(icq_Packet*, int);
+
+#endif /* _ICQ_PACKET_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/icqtypes.h	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,20 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+#ifndef _ICQTYPES_H_
+#define _ICQTYPES_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef _WIN32
+typedef unsigned long DWORD;
+typedef unsigned short WORD;
+typedef unsigned char BYTE;
+typedef unsigned char BOOL;
+#endif
+
+typedef signed long S_DWORD;
+typedef signed short S_WORD;
+typedef signed char S_BYTE;
+
+#endif /* _ICQTYPES_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/list.c	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,273 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+$Id: list.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Log$
+Revision 1.1  2000/11/28 02:22:42  warmenhoven
+icq. whoop de doo
+
+Revision 1.14  2000/07/10 01:44:20  bills
+i really don't learn - removed LIST_TRACE define
+
+Revision 1.13  2000/07/10 01:43:48  bills
+argh - last list buglet fixed, removed free(node) call from list_free
+
+Revision 1.12  2000/07/10 01:31:17  bills
+oops - removed #define LIST_TRACE and #define QUEUE_DEBUG
+
+Revision 1.11  2000/07/10 01:26:30  bills
+added more trace messages, added list_remove_node call in list_free...
+fixes list corruption bug introduced during last commit
+
+Revision 1.10  2000/07/09 22:04:45  bills
+recoded list_free function - this was working very incorrectly!  it was
+only freeing the first node of the list, and then ending.  fixes a memory
+leak.
+
+Revision 1.9  2000/05/10 18:48:56  denis
+list_free() was added to free but do not dispose the list.
+Memory leak with destroying the list was fixed.
+
+Revision 1.8  2000/05/03 18:19:15  denis
+Bug with empty contact list was fixed.
+
+Revision 1.7  2000/01/16 21:26:54  bills
+fixed serious bug in list_remove
+
+Revision 1.6  2000/01/16 03:59:10  bills
+reworked list code so list_nodes don't need to be inside item structures,
+removed strlist code and replaced with generic list calls
+
+Revision 1.5  1999/09/29 19:59:30  bills
+cleanups
+
+Revision 1.4  1999/07/16 11:59:46  denis
+list_first(), list_last(), list_at() added.
+Cleaned up.
+
+*/
+/*
+ * linked list functions
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "list.h"
+
+list *list_new()
+{
+  list *plist=(list *)malloc(sizeof(list));
+
+  plist->head=0;
+  plist->tail=0;
+  plist->count=0;
+
+  return plist;
+}
+
+/* Frees all list nodes and list itself */
+void list_delete(list *plist, void (*item_free_f)(void *))
+{
+  list_free(plist, item_free_f);
+  free(plist);
+}
+
+/* Only frees the list nodes */
+void list_free(list *plist, void (*item_free_f)(void *))
+{
+  list_node *p=plist->head;
+
+#ifdef LIST_TRACE
+  printf("list_free(%p)\n", plist);
+  list_dump(plist);
+#endif
+
+  while(p)
+  {
+    list_node *ptemp=p;
+
+    p=p->next;
+    (*item_free_f)((void *)ptemp->item);
+    list_remove_node(plist, ptemp);
+  }
+}
+
+void list_insert(list *plist, list_node *pnode, void *pitem)
+{
+  list_node *pnew=(list_node *)malloc(sizeof(list_node));
+  pnew->item=pitem;
+
+#ifdef LIST_TRACE
+  printf("inserting %x (node=%x) into list %x\n", pitem, pnew, plist);
+#endif
+ 
+  plist->count++;
+
+  /* null source node signifies insert at end of list */
+  if(!pnode) 
+  {
+    pnew->previous=plist->tail;
+    pnew->next=0;
+    if(plist->tail)
+      plist->tail->next=pnew;
+    plist->tail=pnew;
+
+    if(!plist->head)
+      plist->head=pnew;
+  }
+  else
+  {
+    pnew->previous=pnode->previous;
+    pnew->next=pnode;
+
+    if(pnew->previous)
+      pnew->previous->next=pnew;
+
+    if(pnew->next)
+      pnode->previous=pnew;
+        
+    if(plist->head==pnode)
+      plist->head=pnew;
+  }
+
+#ifdef LIST_TRACE
+  list_dump(plist);
+#endif
+}
+
+void *list_remove_node(list *plist, list_node *p)
+{
+  void *pitem;
+
+  if(!p)
+    return 0;
+
+#ifdef LIST_TRACE
+  printf("removing %x (node=%x) from list %x\n", p->item, p, plist);
+#endif
+
+  plist->count--;
+
+  if(p->next)
+    p->next->previous=p->previous;
+
+  if(p->previous)
+    p->previous->next=p->next;
+
+  if(plist->head==p)
+    plist->head=p->next;
+
+  if(plist->tail==p)
+    plist->tail=p->previous;
+
+  p->next=0;
+  p->previous=0;
+
+#ifdef LIST_TRACE
+  list_dump(plist);
+#endif
+
+  pitem=p->item;
+
+  free(p);
+
+  return pitem;
+}
+
+void *list_traverse(list *plist, int (*item_f)(void *, va_list), ...)
+{
+  list_node *i=plist->head;
+  int f=0;
+  va_list ap;
+
+#ifdef LIST_TRACE
+  printf("list_traverse(%p)\n", plist);
+  list_dump(plist);
+#endif
+  va_start(ap, item_f);
+
+  /* call item_f for each item in list until end of list or item 
+   * function returns 0 */
+  while(i && !f)
+  {
+    list_node *pnext=i->next;
+
+    if(!(f=(*item_f)(i->item, ap)))
+      i=pnext;
+  }
+  va_end(ap);
+  if (i)
+    return i->item;
+  else
+    return 0;
+}
+
+int list_dump(list *plist)
+{
+  list_node *p=plist->head;
+
+  printf("list %x { head=%x, tail=%x, count=%d }\ncontents: ",
+         (int)plist, (int)plist->head, (int)plist->tail, plist->count);
+
+  while(p)
+  {
+    printf("%x, ", (int)p->item);
+    p=p->next;
+  }
+  printf("end\n");
+
+  return 0;
+}
+
+void *list_first(list *plist)
+{
+  if(plist->head)
+    return plist->head->item;
+  else
+    return 0;
+}
+
+void *list_last(list *plist)
+{
+  if(plist->tail)
+    return plist->tail->item;
+  else
+    return 0;
+}
+
+void *list_at(list *plist, int num)
+{
+  list_node *ptr = plist->head;
+  while(ptr && num)
+  {
+    num--;
+    ptr = ptr->next;
+  }
+  if(!num)
+    return ptr->item;
+  else
+    return 0L;
+}
+
+list_node *list_find(list *plist, void *pitem)
+{
+  list_node *p=plist->head;
+
+  while(p)
+  {
+    if(p->item==pitem)
+      return p;
+    p=p->next;
+  }
+  return 0;
+}
+
+void *list_remove(list *plist, void *pitem)
+{
+  list_node *p=list_find(plist, pitem);
+
+  if(p)
+    return list_remove_node(plist, p);
+  else
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/list.h	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,44 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+#ifndef _LIST_H
+#define _LIST_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdarg.h>
+
+#define list_enqueue(plist, p) \
+   list_insert(plist, 0, p)
+
+#define list_dequeue(plist) \
+  list_remove_node(plist, plist->head)
+
+typedef struct list_node_s
+{
+  struct list_node_s *next;
+  struct list_node_s *previous;
+  void *item;
+} list_node;
+
+typedef struct list_s
+{
+  list_node *head;
+  list_node *tail;
+  int count;
+} list;
+
+list *list_new(void);
+void list_delete(list *plist, void (*item_free_f)(void *));
+void list_free(list *plist, void (*item_free_f)(void *));
+void list_insert(list *plist, list_node *pnode, void *pitem);
+void *list_remove(list *plist, void *pitem);
+void *list_traverse(list *plist, int (*item_f)(void *, va_list), ...);
+int list_dump(list *plist);
+void *list_first(list *plist);
+void *list_last(list *plist);
+void *list_at(list *plist, int num);
+list_node *list_find(list *plist, void *pitem);
+void *list_remove_node(list *plist, list_node *p);
+
+#endif /* _LIST_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/proxy.c	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,115 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+$Id: proxy.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Log$
+Revision 1.1  2000/11/28 02:22:42  warmenhoven
+icq. whoop de doo
+
+Revision 1.8  2000/05/10 18:51:23  denis
+icq_Disconnect() now called before icq_Disconnected callback to
+prevent high CPU usage in kicq's "reconnect on disconnect" code.
+
+Revision 1.7  2000/05/03 18:29:15  denis
+Callbacks have been moved to the ICQLINK structure.
+
+Revision 1.6  2000/04/05 14:37:02  denis
+Applied patch from "Guillaume R." <grs@mail.com> for basic Win32
+compatibility.
+
+Revision 1.5  1999/10/07 18:00:59  denis
+proxy.h file removed.
+
+Revision 1.4  1999/07/16 12:01:06  denis
+ICQLINK support added.
+
+Revision 1.3  1999/07/12 15:13:33  cproch
+- added definition of ICQLINK to hold session-specific global variabled
+  applications which have more than one connection are now possible
+- changed nearly every function defintion to support ICQLINK parameter
+
+Revision 1.2  1999/04/14 14:51:42  denis
+Switched from icq_Log callback to icq_Fmt function.
+Cleanups for "strict" compiling (-ansi -pedantic)
+
+Revision 1.1  1999/03/24 11:37:38  denis
+Underscored files with TCP stuff renamed.
+TCP stuff cleaned up
+Function names changed to corresponding names.
+icqlib.c splitted to many small files by subject.
+C++ comments changed to ANSI C comments.
+
+*/
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#ifdef _WIN32
+#include <winsock.h>
+#endif
+
+#include <stdlib.h>
+
+#include "util.h"
+#include "icqtypes.h"
+#include "icq.h"
+#include "icqlib.h"
+
+void icq_HandleProxyResponse(ICQLINK *link)
+{
+  int s;
+  char buf[256];
+#ifdef _WIN32
+  s = recv(link->icq_ProxySok, buf, sizeof(buf), 0);
+#else
+  s = read(link->icq_ProxySok, &buf, sizeof(buf));
+#endif
+  if(s<=0)
+  {
+    icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Connection terminated\n");
+    icq_Disconnect(link);
+    if(link->icq_Disconnected)
+      (*link->icq_Disconnected)(link);
+  }
+}
+
+/*******************
+SOCKS5 Proxy support
+********************/
+void icq_SetProxy(ICQLINK *link, const char *phost, unsigned short pport, int pauth, const char *pname, const char *ppass)
+{
+  if(link->icq_ProxyHost)
+    free(link->icq_ProxyHost);
+  if(link->icq_ProxyName)
+    free(link->icq_ProxyName);
+  if(link->icq_ProxyPass)
+    free(link->icq_ProxyPass);
+  if(strlen(pname)>255)
+  {
+    icq_FmtLog(link, ICQ_LOG_ERROR, "[SOCKS] User name greater than 255 chars\n");
+    link->icq_UseProxy = 0;
+    return;
+  }
+  if(strlen(ppass)>255)
+  {
+    icq_FmtLog(link, ICQ_LOG_ERROR, "[SOCKS] User password greater than 255 chars\n");
+    link->icq_UseProxy = 0;
+    return;
+  }
+  link->icq_UseProxy = 1;
+  link->icq_ProxyHost = strdup(phost);
+  link->icq_ProxyPort = pport;
+  link->icq_ProxyAuth = pauth;
+  link->icq_ProxyName = strdup(pname);
+  link->icq_ProxyPass = strdup(ppass);
+}
+
+void icq_UnsetProxy(ICQLINK *link)
+{
+  link->icq_UseProxy = 0;
+}
+
+int icq_GetProxySok(ICQLINK *link)
+{
+  return link->icq_ProxySok;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/queue.c	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,167 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+$Id: queue.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Log$
+Revision 1.1  2000/11/28 02:22:42  warmenhoven
+icq. whoop de doo
+
+Revision 1.9  2000/07/10 01:31:17  bills
+oops - removed #define LIST_TRACE and #define QUEUE_DEBUG
+
+Revision 1.8  2000/07/10 01:26:56  bills
+added more trace messages, reworked packet delete handling: now happens
+during _icq_UDEQueueItemFree rather than during icq_UDPQueueDelSeq - fixes
+memory leak
+
+Revision 1.7  2000/07/09 22:07:37  bills
+use new list_free
+
+Revision 1.6  2000/06/25 16:30:05  denis
+Some sanity checks were added to icq_UDPQueueDelete() and
+icq_UDPQueueFree()
+
+Revision 1.5  2000/05/10 19:06:59  denis
+UDP outgoing packet queue was implemented.
+
+Revision 1.4  2000/03/30 14:15:28  denis
+Fixed FreeBSD warning about obsolete malloc.h header.
+
+Revision 1.3  2000/01/16 03:59:10  bills
+reworked list code so list_nodes don't need to be inside item structures,
+removed strlist code and replaced with generic list calls
+
+Revision 1.2  1999/09/29 17:06:47  denis
+ICQLINK compatibility added.
+
+Revision 1.1  1999/07/16 12:12:13  denis
+Initial support for outgoing packet queue added.
+
+*/
+
+#include <stdlib.h>
+#include <time.h>
+
+#include "queue.h"
+#include "list.h"
+
+void icq_UDPQueueNew(ICQLINK *link)
+{
+  link->icq_UDPQueue = list_new();
+  link->icq_UDPExpireInterval = 15; /* expire interval = 15 sec */
+}
+
+void icq_UDPQueuePut(ICQLINK *link, icq_Packet *p, int attempt)
+{
+  icq_UDPQueueItem *ptr = (icq_UDPQueueItem*)malloc(sizeof(icq_UDPQueueItem));
+#ifdef QUEUE_DEBUG
+  printf("icq_UDPQueuePut(seq=0x%04X, cmd=0x%04X)\n", icq_PacketReadUDPOutSeq1(p),
+         icq_PacketReadUDPOutCmd(p));
+#endif
+  ptr->attempts = attempt;
+  ptr->expire = time(0L)+link->icq_UDPExpireInterval;
+  ptr->pack = p;
+#ifdef QUEUE_DEBUG
+  printf("enqueuing queueitem %p\n", ptr);
+#endif
+  list_enqueue(link->icq_UDPQueue, ptr);
+}
+
+icq_Packet *icq_UDPQueueGet(ICQLINK *link)
+{
+  icq_UDPQueueItem *ptr = (icq_UDPQueueItem*)list_first(link->icq_UDPQueue);
+  icq_Packet *pack = 0L;
+  if(ptr)
+  {
+    pack = ptr->pack;
+    list_remove(link->icq_UDPQueue, (list_node*)ptr);
+  }
+#ifdef QUEUE_DEBUG
+  if(pack)
+    printf("icq_UDPQueueGet(cmd=0x%04X)\n", icq_PacketReadUDPOutCmd(pack));
+#endif
+  return pack;
+}
+
+icq_Packet *icq_UDPQueuePeek(ICQLINK *link)
+{
+  icq_UDPQueueItem *ptr = (icq_UDPQueueItem*)list_first(link->icq_UDPQueue);
+  if(ptr)
+    return ptr->pack;
+  else
+    return 0L;
+}
+
+void _icq_UDPQueueItemFree(void *p)
+{
+  icq_UDPQueueItem *pitem=(icq_UDPQueueItem *)p;
+
+#ifdef QUEUE_DEBUG
+  printf("_icq_UDPQueueItemFree(%p)\n", p);
+#endif
+
+  if (pitem->pack)
+    icq_PacketDelete(pitem->pack);
+
+  free(p);
+}
+
+/* Frees the queue and dispose it */
+void icq_UDPQueueDelete(ICQLINK *link)
+{
+#ifdef QUEUE_DEBUG
+  printf("icq_UDPQueueDelete\n");
+#endif
+  if(link->icq_UDPQueue)
+  {
+    list_delete(link->icq_UDPQueue, _icq_UDPQueueItemFree);
+    link->icq_UDPQueue = 0;
+  }
+}
+
+/* Only frees the queue */
+void icq_UDPQueueFree(ICQLINK *link)
+{
+#ifdef QUEUE_DEBUG
+  printf("icq_UDPQueueFree\n");
+#endif
+  if(link->icq_UDPQueue)
+    list_free(link->icq_UDPQueue, _icq_UDPQueueItemFree);
+}
+
+int icq_UDPQueueFindSeq(void *p, va_list data)
+{
+  WORD seq=va_arg(data, WORD);
+  return icq_PacketReadUDPOutSeq1(((icq_UDPQueueItem *)p)->pack) == seq;
+}
+
+void icq_UDPQueueDelSeq(ICQLINK *link, WORD seq)
+{
+  icq_UDPQueueItem *ptr;
+#ifdef QUEUE_DEBUG
+  printf("icq_UDPQueueDelSeq(seq=0x%04X", seq);
+#endif
+  ptr = list_traverse(link->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);
+    _icq_UDPQueueItemFree(ptr);
+  }
+#ifdef QUEUE_DEBUG
+  printf(")\n");
+#endif
+}
+
+long icq_UDPQueueInterval(ICQLINK *link)
+{
+  long interval;
+  icq_UDPQueueItem *ptr = (icq_UDPQueueItem*)list_first(link->icq_UDPQueue);
+  if(ptr)
+  {
+    interval = ptr->expire - time(0L);
+    return interval>=0?interval:0;
+  }
+  return -1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/queue.h	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,29 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+#ifndef _QUEUE_H_
+#define _QUEUE_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "icq.h"
+#include "icqpacket.h"
+
+typedef struct udp_item
+{
+  unsigned char attempts;
+  unsigned long expire;
+  icq_Packet *pack;
+} icq_UDPQueueItem;
+
+void icq_UDPQueueNew(ICQLINK*);
+void icq_UDPQueueFree(ICQLINK*);
+void icq_UDPQueuePut(ICQLINK*, icq_Packet*, int);
+icq_Packet *icq_UDPQueueGet(ICQLINK*);
+icq_Packet *icq_UDPQueuePeek(ICQLINK*);
+void icq_UDPQueueDelete(ICQLINK*);
+void icq_UDPQueueFree(ICQLINK*);
+void icq_UDPQueueDelSeq(ICQLINK*, WORD);
+long icq_UDPQueueInterval(ICQLINK *);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/stdpackets.c	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,563 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+$Id: stdpackets.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Log$
+Revision 1.1  2000/11/28 02:22:42  warmenhoven
+icq. whoop de doo
+
+Revision 1.10  2000/06/15 01:51:23  bills
+added creation functions for cancel and refuse operations
+
+Revision 1.9  2000/05/04 15:50:38  bills
+warning cleanups
+
+Revision 1.8  2000/04/10 18:11:45  denis
+ANSI cleanups.
+
+Revision 1.7  2000/04/06 16:38:04  denis
+icq_*Send*Seq() functions with specified sequence number were added.
+
+Revision 1.6  2000/02/07 02:35:13  bills
+slightly modified chat packets
+
+Revision 1.5  2000/01/20 19:59:15  bills
+first implementation of sending file requests
+
+Revision 1.4  1999/09/29 20:12:32  bills
+tcp_link*->icq_TCPLink*
+
+Revision 1.3  1999/09/29 17:07:48  denis
+Host/network byteorder cleanups.
+
+Revision 1.2  1999/07/16 15:45:20  denis
+Cleaned up.
+
+Revision 1.1  1999/07/16 12:13:11  denis
+UDP packets support added.
+tcppackets.[ch] files renamed to stdpackets.[ch]
+
+Revision 1.9  1999/07/12 15:13:39  cproch
+- added definition of ICQLINK to hold session-specific global variabled
+  applications which have more than one connection are now possible
+- changed nearly every function defintion to support ICQLINK parameter
+
+Revision 1.8  1999/05/03 21:41:28  bills
+initial file xfer support added- untested
+
+Revision 1.7  1999/04/17 19:39:09  bills
+added new functions to create chat packets. removed unnecessary code.
+added new function to create URL ack packet.
+
+Revision 1.6  1999/04/14 15:08:39  denis
+Cleanups for "strict" compiling (-ansi -pedantic)
+
+*/
+
+#include <stdlib.h>
+
+#include "icqtypes.h"
+#include "icq.h"
+#include "icqlib.h"
+#include "tcp.h"
+#include "stdpackets.h"
+
+icq_Packet *icq_TCPCreateInitPacket(icq_TCPLink *plink)
+{
+  icq_Packet *p=icq_PacketNew();
+
+  if(p)
+  {
+    int type=plink->type;
+
+    icq_PacketAppend8(p, 0xFF);
+    icq_PacketAppend32(p, ICQ_TCP_VER);
+    if(type==TCP_LINK_MESSAGE)
+      icq_PacketAppend32n(p, htons(plink->icqlink->icq_TCPSrvPort));
+    else
+      icq_PacketAppend32(p, 0x00000000);
+    icq_PacketAppend32(p, plink->icqlink->icq_Uin);
+    icq_PacketAppend32n(p, htonl(plink->icqlink->icq_OurIP));
+    icq_PacketAppend32n(p, htonl(plink->icqlink->icq_OurIP));
+    icq_PacketAppend8(p, 0x04);
+    if(type==TCP_LINK_FILE || type==TCP_LINK_CHAT)
+      icq_PacketAppend32(p, ntohs(plink->socket_address.sin_port));
+    else
+      icq_PacketAppend32(p, 0x00000000);
+
+  }
+
+  return p;
+}
+
+icq_Packet *icq_TCPCreateStdPacket(icq_TCPLink *plink, WORD icq_TCPCommand,
+               WORD type, const unsigned char *msg, WORD status,
+               WORD msg_command)
+{
+  icq_Packet *p=icq_PacketNew();
+
+  if(p)
+  {
+    icq_PacketAppend32(p, plink->icqlink->icq_Uin);
+    icq_PacketAppend16(p, ICQ_TCP_VER);
+    icq_PacketAppend16(p, icq_TCPCommand);
+    icq_PacketAppend16(p, 0x0000);
+    icq_PacketAppend32(p, plink->icqlink->icq_Uin);
+
+    icq_PacketAppend16(p, type);
+    icq_PacketAppendString(p, (char*)msg);
+      
+    /* FIXME: this should be the address the server returns to us,
+     * link->icq_OurIp */
+    icq_PacketAppend32(p, plink->socket_address.sin_addr.s_addr); 
+    icq_PacketAppend32(p, plink->socket_address.sin_addr.s_addr);
+    icq_PacketAppend32(p, ntohs(plink->socket_address.sin_port));
+    icq_PacketAppend8(p, 0x04);
+    icq_PacketAppend16(p, status);
+    icq_PacketAppend16(p, msg_command);
+  }
+
+  return p;
+}
+
+icq_Packet *icq_TCPCreateMessagePacket(icq_TCPLink *plink, const unsigned char *message)
+{
+  icq_Packet *p=icq_TCPCreateStdPacket(
+    plink,
+    ICQ_TCP_MESSAGE,
+    ICQ_TCP_MSG_MSG,
+    message,
+    0, /* status */
+    ICQ_TCP_MSG_REAL);
+
+  return p;
+}
+
+icq_Packet *icq_TCPCreateURLPacket(icq_TCPLink *plink, const char *message,
+   const char *url)
+{
+  icq_Packet *p;
+  unsigned char *str=(unsigned char*)malloc(strlen(message)+strlen(url)+2);
+
+  strcpy((char*)str, message);
+  *(str+strlen(message))=0xFE;
+  strcpy((char*)(str+strlen(message)+1), url);
+
+  p=icq_TCPCreateStdPacket(
+    plink,
+    ICQ_TCP_MESSAGE,
+    ICQ_TCP_MSG_URL,
+    str,
+    0, /* status */
+    ICQ_TCP_MSG_REAL);
+
+  free(str);
+
+  return p;
+}
+
+icq_Packet *icq_TCPCreateChatReqPacket(icq_TCPLink *plink, const unsigned char *message)
+{
+  icq_Packet *p=icq_TCPCreateStdPacket(
+    plink,
+    ICQ_TCP_MESSAGE,
+    ICQ_TCP_MSG_CHAT,
+    message,
+    0, /* status */
+    ICQ_TCP_MSG_REAL);
+
+  icq_PacketAppendString(p, 0);
+
+  icq_PacketAppend16(p, 0x0000);
+  icq_PacketAppend16(p, 0x0000);
+  icq_PacketAppend32(p, 0x00000000);
+
+  return p;
+}
+
+icq_Packet *icq_TCPCreateChatReqAck(icq_TCPLink *plink, WORD port)
+{
+  icq_Packet *p=icq_TCPCreateStdPacket(
+    plink,
+    ICQ_TCP_ACK,
+    ICQ_TCP_MSG_CHAT,
+    0,
+    0, /* status */
+    ICQ_TCP_MSG_ACK);
+
+  icq_PacketAppendString(p, 0);
+
+  icq_PacketAppend16(p, htons(port));
+  icq_PacketAppend16(p, 0x0000);
+  icq_PacketAppend32(p, port);
+
+  return p;
+}
+
+icq_Packet *icq_TCPCreateChatReqRefuse(icq_TCPLink *plink, WORD port,
+  const char *reason)
+{
+  icq_Packet *p=icq_TCPCreateStdPacket(
+    plink,
+    ICQ_TCP_ACK,
+    ICQ_TCP_MSG_CHAT,
+    reason,
+    ICQ_TCP_STATUS_REFUSE,
+    ICQ_TCP_MSG_ACK);
+
+  icq_PacketAppendString(p, 0);
+
+  icq_PacketAppend16(p, htons(port));
+  icq_PacketAppend16(p, 0x0000);
+  icq_PacketAppend32(p, port);
+
+  return p;
+}
+
+icq_Packet *icq_TCPCreateChatReqCancel(icq_TCPLink *plink, WORD port)
+{
+  icq_Packet *p=icq_TCPCreateStdPacket(
+    plink,
+    ICQ_TCP_CANCEL,
+    ICQ_TCP_MSG_CHAT,
+    0,
+    0, /* status */
+    ICQ_TCP_MSG_ACK);
+
+  icq_PacketAppendString(p, 0);
+
+  icq_PacketAppend16(p, htons(port));
+  icq_PacketAppend16(p, 0x0000);
+  icq_PacketAppend32(p, port);
+
+  return p;
+}
+
+icq_Packet *icq_TCPCreateFileReqAck(icq_TCPLink *plink, WORD port)
+{
+  icq_Packet *p=icq_TCPCreateStdPacket(
+    plink,
+    ICQ_TCP_ACK,
+    ICQ_TCP_MSG_FILE,
+    0,
+    0, /* status */
+    ICQ_TCP_MSG_ACK);
+
+  icq_PacketAppend16(p, htons(port));
+  icq_PacketAppend16(p, 0x0000);
+  icq_PacketAppendString(p, 0);
+  icq_PacketAppend32(p, 0x00000000);
+  icq_PacketAppend32(p, port);
+
+  return p;
+}
+
+icq_Packet *icq_TCPCreateFileReqRefuse(icq_TCPLink *plink, WORD port,
+  const char *reason)
+{
+  icq_Packet *p=icq_TCPCreateStdPacket(
+    plink,
+    ICQ_TCP_ACK,
+    ICQ_TCP_MSG_FILE,
+    reason,
+    ICQ_TCP_STATUS_REFUSE,
+    ICQ_TCP_MSG_ACK);
+
+  icq_PacketAppend16(p, htons(port));
+  icq_PacketAppend16(p, 0x0000);
+  icq_PacketAppendString(p, 0);
+  icq_PacketAppend32(p, 0x00000000);
+  icq_PacketAppend32(p, port);
+
+  return p;
+}
+
+icq_Packet *icq_TCPCreateFileReqCancel(icq_TCPLink *plink, WORD port)
+{
+  icq_Packet *p=icq_TCPCreateStdPacket(
+    plink,
+    ICQ_TCP_CANCEL,
+    ICQ_TCP_MSG_FILE,
+    0,
+    0, /* status */
+    ICQ_TCP_MSG_ACK);
+
+  icq_PacketAppend16(p, htons(port));
+  icq_PacketAppend16(p, 0x0000);
+  icq_PacketAppendString(p, 0);
+  icq_PacketAppend32(p, 0x00000000);
+  icq_PacketAppend32(p, port);
+
+  return p;
+}
+
+icq_Packet *icq_TCPCreateChatInfoPacket(icq_TCPLink *plink, const char *name, 
+   DWORD foreground, DWORD background)
+{
+   icq_Packet *p=icq_PacketNew();
+
+   icq_PacketAppend32(p, 0x00000065);
+   icq_PacketAppend32(p, 0xfffffffa);
+   icq_PacketAppend32(p, plink->icqlink->icq_Uin);
+   icq_PacketAppendString(p, name);
+   icq_PacketAppend16(p, plink->socket_address.sin_port);
+   icq_PacketAppend32(p, foreground);
+   icq_PacketAppend32(p, background);
+   icq_PacketAppend8(p, 0x00);
+
+   return p;
+
+}
+
+icq_Packet *icq_TCPCreateChatInfo2Packet(icq_TCPLink *plink, const char *name, 
+   DWORD foreground, DWORD background)
+{
+   icq_Packet *p=icq_PacketNew();
+
+   icq_PacketAppend32(p, 0x00000064);
+   icq_PacketAppend32(p, plink->icqlink->icq_Uin);
+   icq_PacketAppendString(p, name);
+   icq_PacketAppend32(p, foreground);
+   icq_PacketAppend32(p, background);
+
+   icq_PacketAppend32(p, 0x00070004);
+   icq_PacketAppend32(p, 0x00000000);
+   icq_PacketAppend32n(p, htonl(plink->icqlink->icq_OurIP));
+   icq_PacketAppend32n(p, htonl(plink->icqlink->icq_OurIP));
+   icq_PacketAppend8(p, 0x04);
+   icq_PacketAppend16(p, 0x0000);
+   icq_PacketAppend32(p, 0x000a);
+   icq_PacketAppend32(p, 0x0000);
+   icq_PacketAppendString(p, "Courier New");
+   icq_PacketAppend8(p, 204);
+   icq_PacketAppend8(p, 49);
+   icq_PacketAppend8(p, 0x00);
+
+   return p;
+}
+
+icq_Packet *icq_TCPCreateChatFontInfoPacket(icq_TCPLink *plink)
+{
+   icq_Packet *p=icq_PacketNew();
+   
+   icq_PacketAppend32(p, 0x00070004);
+   icq_PacketAppend32(p, 0x00000000);
+   icq_PacketAppend32n(p, htonl(plink->icqlink->icq_OurIP));
+   icq_PacketAppend32n(p, htonl(plink->icqlink->icq_OurIP));
+   icq_PacketAppend8(p, 0x04);
+   icq_PacketAppend16(p, ntohs(plink->socket_address.sin_port)); /* Zero ? */
+   icq_PacketAppend32(p, 0x000a);
+   icq_PacketAppend32(p, 0x0000);
+   icq_PacketAppendString(p, "Courier New");
+   icq_PacketAppend8(p, 204);
+   icq_PacketAppend8(p, 49);
+   icq_PacketAppend8(p, 0x00);
+
+   return p;
+}
+
+
+icq_Packet *icq_TCPCreateFileReqPacket(icq_TCPLink *plink, 
+  const char *message, const char *filename, unsigned long size)
+{
+  icq_Packet *p=icq_TCPCreateStdPacket(
+    plink,
+    ICQ_TCP_MESSAGE,
+    ICQ_TCP_MSG_FILE,
+    (const unsigned char*)message,
+    0, /* status */
+    ICQ_TCP_MSG_REAL);
+
+  icq_PacketAppend16(p, 0x0000);
+  icq_PacketAppend16(p, 0x0000);
+
+  icq_PacketAppendString(p, filename);
+
+  icq_PacketAppend32(p, size);
+  icq_PacketAppend32(p, 0x00000000);
+
+  return p;
+}
+
+void icq_TCPAppendSequence(ICQLINK *link, icq_Packet *p)
+{
+  p->id=link->icq_TCPSequence--;
+  icq_PacketEnd(p);
+  icq_PacketAppend32(p, p->id);
+}
+
+void icq_TCPAppendSequenceN(ICQLINK *link, icq_Packet *p, DWORD seq)
+{
+  (void)link;
+  p->id=seq;
+  icq_PacketEnd(p);
+  icq_PacketAppend32(p, p->id);
+}
+
+icq_Packet *icq_TCPCreateMessageAck(icq_TCPLink *plink, const unsigned char *message)
+{
+  icq_Packet *p=icq_TCPCreateStdPacket(
+    plink,
+    ICQ_TCP_ACK,
+    ICQ_TCP_MSG_MSG,
+    message,
+    0, /* status */
+    ICQ_TCP_MSG_ACK);
+
+   return p;
+}
+
+icq_Packet *icq_TCPCreateURLAck(icq_TCPLink *plink, const unsigned char *message)
+{
+  icq_Packet *p=icq_TCPCreateStdPacket(
+    plink,
+    ICQ_TCP_ACK,
+    ICQ_TCP_MSG_URL,
+    message,
+    0, /* status */
+    ICQ_TCP_MSG_ACK);
+
+   return p;
+}
+
+
+icq_Packet *icq_TCPCreateFile00Packet(DWORD num_files, DWORD total_bytes,
+  DWORD speed, const char *name)
+{
+  icq_Packet *p=icq_PacketNew();
+
+  if(p)
+  {
+    icq_PacketAppend8(p, 0x00);
+    icq_PacketAppend32(p, 0x00000000);
+    icq_PacketAppend32(p, num_files);
+    icq_PacketAppend32(p, total_bytes);
+    icq_PacketAppend32(p, speed);
+    icq_PacketAppendString(p, name);
+  }
+
+  return p;
+}
+
+icq_Packet *icq_TCPCreateFile01Packet(DWORD speed, const char *name)
+{
+  icq_Packet *p=icq_PacketNew();
+
+  if(p)
+  {
+    icq_PacketAppend8(p, 0x01);
+    icq_PacketAppend32(p, speed);
+    icq_PacketAppendString(p, name);
+  }
+
+  return p;
+}
+
+icq_Packet *icq_TCPCreateFile02Packet(const char *filename, DWORD filesize,
+  DWORD speed)
+{
+  icq_Packet *p=icq_PacketNew();
+
+  if(p)
+  {
+    icq_PacketAppend8(p, 0x02);
+    icq_PacketAppend8(p, 0x00);
+    icq_PacketAppendString(p, filename);
+    icq_PacketAppendString(p, 0);
+    icq_PacketAppend32(p, filesize);
+    icq_PacketAppend32(p, 0x00000000);    
+    icq_PacketAppend32(p, speed);
+  }
+
+  return p;
+}
+
+icq_Packet *icq_TCPCreateFile03Packet(DWORD filesize, DWORD speed)
+{
+  icq_Packet *p=icq_PacketNew();
+
+  if(p)
+  {
+    icq_PacketAppend8(p, 0x03);
+    icq_PacketAppend32(p, filesize);
+    icq_PacketAppend32(p, 0x00000000);
+    icq_PacketAppend32(p, speed);
+  }
+
+  return p;
+}
+
+icq_Packet *icq_TCPCreateFile04Packet(DWORD filenum)
+{
+  icq_Packet *p=icq_PacketNew();
+
+  if(p)
+  {
+    icq_PacketAppend8(p, 0x04);
+    icq_PacketAppend32(p, filenum);
+  }
+
+  return p;
+}
+
+icq_Packet *icq_TCPCreateFile05Packet(DWORD speed)
+{
+  icq_Packet *p=icq_PacketNew();
+
+  if(p)
+  {
+    icq_PacketAppend8(p, 0x05);
+    icq_PacketAppend32(p, speed);
+  }
+
+  return p;
+}
+
+icq_Packet *icq_TCPCreateFile06Packet(int length, void *data)
+{
+  icq_Packet *p=icq_PacketNew();
+
+  if(p)
+  {
+    icq_PacketAppend8(p, 0x06);
+    icq_PacketAppend(p, data, length);
+  }
+
+  return p;
+}
+
+icq_Packet *icq_UDPCreateStdPacket(ICQLINK *link, WORD cmd)
+{
+  icq_Packet *p = icq_PacketNew();
+
+/*  if(!link->icq_UDPSession)
+    link->icq_UDPSession = rand() & 0x3FFFFFFF;
+  if(!link->icq_UDPSeqNum2)
+    link->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_PacketAppend16(p, cmd);                    /* cmd */
+  icq_PacketAppend16(p, link->icq_UDPSeqNum1++); /* seq1 */
+  icq_PacketAppend16(p, link->icq_UDPSeqNum2++); /* seq2 */
+  icq_PacketAppend32(p, 0);                      /* checkcode */
+
+  return p;
+}
+
+icq_Packet *icq_UDPCreateStdSeqPacket(ICQLINK *link, WORD cmd, WORD seq)
+{
+  icq_Packet *p = icq_PacketNew();
+
+  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_PacketAppend16(p, cmd);                    /* cmd */
+  icq_PacketAppend16(p, seq);                    /* seq1 */
+  icq_PacketAppend16(p, 0);                      /* seq2 */
+  icq_PacketAppend32(p, 0);                      /* checkcode */
+
+  return p;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/stdpackets.h	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,102 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+#ifndef _ICQTCPPACKETS_H
+#define _ICQTCPPACKETS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define ICQ_UDP_VER            0x0005
+#define ICQ_TCP_VER            0x0003
+
+/* TCP Packet Commands */
+#define ICQ_TCP_HELLO            0xFF
+#define ICQ_TCP_CANCEL           0x07D0
+#define ICQ_TCP_ACK              0x07DA
+#define ICQ_TCP_MESSAGE          0x07EE
+
+/* TCP Message Types */
+#define ICQ_TCP_MSG_MSG          0x0001
+#define ICQ_TCP_MSG_CHAT         0x0002
+#define ICQ_TCP_MSG_FILE         0x0003
+#define ICQ_TCP_MSG_URL          0x0004
+#define ICQ_TCP_MSG_READAWAY     0x03E8
+#define ICQ_TCP_MSG_READOCCUPIED 0x03E9
+#define ICQ_TCP_MSG_READNA       0x03EA
+#define ICQ_TCP_MSG_READDND      0x03EB
+#define ICQ_TCP_MSG_READFFC      0x03EC
+
+/* TCP Message Command Types */
+#define ICQ_TCP_MSG_ACK          0x0000
+#define ICQ_TCP_MSG_AUTO         0x0000
+#define ICQ_TCP_MSG_REAL         0x0010
+#define ICQ_TCP_MSG_LIST         0x0020
+#define ICQ_TCP_MSG_URGENT       0x0040
+#define ICQ_TCP_MSG_INVISIBLE    0x0090
+#define ICQ_TCP_MSG_UNK_1        0x00A0
+#define ICQ_TCP_MSG_AWAY         0x0110
+#define ICQ_TCP_MSG_OCCUPIED     0x0210
+#define ICQ_TCP_MSG_UNK_2        0x0802
+#define ICQ_TCP_MSG_NA           0x0810
+#define ICQ_TCP_MSG_NA_2         0x0820
+#define ICQ_TCP_MSG_DND          0x1010
+
+/* TCP Message Statuses */
+#define ICQ_TCP_STATUS_ONLINE      0x0000
+#define ICQ_TCP_STATUS_REFUSE      0x0001
+#define ICQ_TCP_STATUS_AWAY        0x0004
+#define ICQ_TCP_STATUS_OCCUPIED    0x0009
+#define ICQ_TCP_STATUS_DND         0x000A
+#define ICQ_TCP_STATUS_NA          0x000E
+#define ICQ_TCP_STATUS_FREE_CHAT   ICQ_TCP_STATUS_ONLINE
+#define ICQ_TCP_STATUS_INVISIBLE   ICQ_TCP_STATUS_ONLINE
+
+#include "icqpacket.h"
+#include "tcplink.h"
+
+icq_Packet *icq_TCPCreateInitPacket(icq_TCPLink *plink);
+icq_Packet *icq_TCPCreateStdPacket(icq_TCPLink *plink, WORD icq_TCPCommand,
+               WORD type, const unsigned char *msg, WORD status, 
+               WORD msg_command);
+icq_Packet *icq_TCPCreateMessagePacket(icq_TCPLink *plink, const unsigned char *message);
+icq_Packet *icq_TCPCreateURLPacket(icq_TCPLink *plink, const char *message,
+   const char *url);
+icq_Packet *icq_TCPCreateChatReqPacket(icq_TCPLink *plink,  const unsigned char *message);
+icq_Packet *icq_TCPCreateFileReqPacket(icq_TCPLink *plink, 
+   const char *message, const char *filename, DWORD size);
+void icq_TCPAppendSequence(ICQLINK *link, icq_Packet *p);
+void icq_TCPAppendSequenceN(ICQLINK *link, icq_Packet *p, DWORD seq);
+
+icq_Packet *icq_TCPCreateMessageAck(icq_TCPLink *plink, const unsigned char *message);
+icq_Packet *icq_TCPCreateURLAck(icq_TCPLink *plink, const unsigned char *message);
+icq_Packet *icq_TCPCreateWebPagerAck(icq_TCPLink *plink, const unsigned char *message);
+icq_Packet *icq_TCPCreateChatReqAck(icq_TCPLink *plink, WORD port);
+icq_Packet *icq_TCPCreateChatReqCancel(icq_TCPLink *plink, WORD port);
+icq_Packet *icq_TCPCreateChatReqRefuse(icq_TCPLink *plink, WORD port,
+   const char *reason);
+icq_Packet *icq_TCPCreateFileReqAck(icq_TCPLink *plink, WORD port);
+icq_Packet *icq_TCPCreateFileReqCancel(icq_TCPLink *plink, WORD port);
+icq_Packet *icq_TCPCreateFileReqRefuse(icq_TCPLink *plink, WORD port,
+   const char *reason);
+
+icq_Packet *icq_TCPCreateChatInfoPacket(icq_TCPLink *plink, const char *name, 
+   DWORD foreground, DWORD background);
+icq_Packet *icq_TCPCreateChatInfo2Packet(icq_TCPLink *plink, const char *name,
+   DWORD foreground, DWORD background);
+icq_Packet *icq_TCPCreateChatFontInfoPacket(icq_TCPLink *plink);
+
+icq_Packet *icq_TCPCreateFile00Packet(DWORD num_files, DWORD total_bytes, DWORD speed, const char *name);
+icq_Packet *icq_TCPCreateFile01Packet(DWORD speed, const char *name);
+icq_Packet *icq_TCPCreateFile02Packet(const char *filename, DWORD filesize, DWORD speed);
+icq_Packet *icq_TCPCreateFile03Packet(DWORD filesize, DWORD speed);
+icq_Packet *icq_TCPCreateFile04Packet(DWORD filenum);
+icq_Packet *icq_TCPCreateFile05Packet(DWORD speed);
+icq_Packet *icq_TCPCreateFile06Packet(int length, void *data);
+
+icq_Packet *icq_UDPCreateStdPacket(ICQLINK *link, WORD cmd);
+icq_Packet *icq_UDPCreateStdSeqPacket(ICQLINK *link, WORD cmd, WORD seq);
+
+#endif /* _ICQTCPPACKETS_H */
+
+/* From `tcppackets.c': */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/tcp.c	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,639 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+$Id: tcp.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Log$
+Revision 1.1  2000/11/28 02:22:42  warmenhoven
+icq. whoop de doo
+
+Revision 1.36  2000/07/09 22:19:35  bills
+added new *Close functions, use *Close functions instead of *Delete
+where correct, and misc cleanup
+
+Revision 1.35  2000/06/15 01:52:16  bills
+added Cancel and Refuse functions for chat and file reqs, changed packet
+sending code to use new icq_TCPLinkSendSeq function to elimitane duplicate
+code, removed *Seq functions, renamed chat req functions
+
+Revision 1.34  2000/05/04 15:57:20  bills
+Reworked file transfer notification, small bugfixes, and cleanups.
+
+Revision 1.33  2000/04/10 18:11:45  denis
+ANSI cleanups.
+
+Revision 1.32  2000/04/10 16:36:04  denis
+Some more Win32 compatibility from Guillaume Rosanis <grs@mail.com>
+
+Revision 1.31  2000/04/06 16:38:04  denis
+icq_*Send*Seq() functions with specified sequence number were added.
+
+Revision 1.30  2000/04/05 14:37:02  denis
+Applied patch from "Guillaume R." <grs@mail.com> for basic Win32
+compatibility.
+
+Revision 1.29  2000/02/15 04:02:41  bills
+warning cleanup
+
+Revision 1.28  2000/02/15 03:58:20  bills
+use new icq_ChatRusConv_n function in icq_TCPSendChatData,
+new icq_TCPSendChatData_n function
+
+Revision 1.27  2000/02/07 02:40:23  bills
+new code for SOCKS connections, more cyrillic translations
+
+Revision 1.26  2000/01/20 19:59:15  bills
+first implementation of sending file requests
+
+Revision 1.25  2000/01/16 21:28:24  bills
+renamed icq_TCPAcceptFileReq to icq_AcceptFileRequest, moved file request
+functions to new file session code
+
+Revision 1.24  2000/01/16 03:59:10  bills
+reworked list code so list_nodes don't need to be inside item structures,
+removed strlist code and replaced with generic list calls
+
+Revision 1.23  1999/12/27 16:10:04  bills
+fixed buy in icq_TCPAcceptFileReq, added icq_TCPFileSetSpeed
+
+Revision 1.22  1999/12/21 00:29:59  bills
+moved _process_packet logic into tcplink::icq_TCPLinkProcessReceived,
+removed unnecessary icq_TCPSendFile??Packet functions
+
+Revision 1.21  1999/12/14 03:31:48  bills
+fixed double delete bug in _handle_ready_sockets, added code to implement
+connect timeout
+
+Revision 1.20  1999/11/30 09:44:31  bills
+added file session logic
+
+Revision 1.19  1999/09/29 20:07:12  bills
+cleanups, moved connect logic from _handle_ready_sockets to
+icq_TCPLinkOnConnect, tcp_link->icq_TCPLink
+
+Revision 1.18  1999/09/29 17:08:48  denis
+Cleanups.
+
+Revision 1.17  1999/07/18 20:19:56  bills
+added better log messages
+
+Revision 1.16  1999/07/16 15:45:56  denis
+Cleaned up.
+
+Revision 1.15  1999/07/16 12:14:13  denis
+tcp_packet* functions renamed to icq_Packet*
+Cleaned up.
+
+Revision 1.14  1999/07/12 15:13:34  cproch
+- added definition of ICQLINK to hold session-specific global variabled
+  applications which have more than one connection are now possible
+- changed nearly every function defintion to support ICQLINK parameter
+
+Revision 1.13  1999/07/03 06:33:49  lord
+. byte order conversion macros added
+. some compilation warnings removed
+
+Revision 1.12  1999/06/30 13:52:22  bills
+implemented non-blocking connects
+
+Revision 1.11  1999/05/03 21:41:26  bills
+initial file xfer support added- untested
+
+Revision 1.10  1999/04/29 09:35:41  denis
+Cleanups, warning removed
+
+Revision 1.9  1999/04/17 19:30:50  bills
+_major_ restructuring.  all tcp sockets (including listening sockets) are
+kept in global linked list, icq_TCPLinks. accept and listen functions
+moved to tcplink.c.  changed return values of Send* functions to DWORD.
+
+Revision 1.8  1999/04/14 14:57:05  denis
+Cleanups for "strict" compiling (-ansi -pedantic)
+Parameter port added to function icq_TCPCreateListeningSocket()
+
+*/
+
+/*
+   Peer-to-peer ICQ protocol implementation
+
+   Uses version 2 of the ICQ protocol
+
+   Thanks to Douglas F. McLaughlin and many others for
+   packet details (see tcp02.txt)
+
+*/
+
+#include <stdlib.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#include <fcntl.h>
+#include <stdarg.h>
+#include <errno.h>
+
+#include <sys/types.h>
+
+#ifdef _WIN32
+#include <winsock.h>
+#else
+#include <sys/socket.h>
+#endif
+
+#include <sys/stat.h>
+
+#ifndef _WIN32
+#include <sys/time.h>
+#endif
+
+#include "icqtypes.h"
+#include "icqlib.h"
+
+#include "tcp.h"
+#include "stdpackets.h"
+#include "list.h"
+#include "tcplink.h"
+#include "chatsession.h"
+#include "filesession.h"
+
+/**
+ Initializes structures necessary for TCP use.  Not required by user
+ programs.
+
+ \return true on error
+*/
+ 
+int icq_TCPInit(ICQLINK *link)
+{
+  icq_TCPLink *plink;
+
+  /* allocate lists */
+  link->icq_TCPLinks=list_new();
+  link->icq_ChatSessions=list_new();
+  link->icq_FileSessions=list_new();
+
+  /* only the main listening socket gets created upon initialization -
+   * the other two are created when necessary */
+  plink=icq_TCPLinkNew( link );
+  icq_TCPLinkListen(plink);
+  link->icq_TCPSrvPort=ntohs(plink->socket_address.sin_port);
+
+  /* reset tcp sequence number */
+  link->icq_TCPSequence=0xfffffffe;
+
+  return 0;
+}
+
+void icq_TCPDone(ICQLINK *link)
+{
+  /* 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);
+}
+
+/* helper function for icq_TCPMain */
+int _generate_fds(void *p, va_list data)
+{
+  icq_TCPLink *plink=(icq_TCPLink *)p;
+  ICQLINK *icqlink = plink->icqlink;
+
+  (void)data;
+
+  if(plink->socket>-1)
+  {
+    int socket=plink->socket;
+
+    FD_SET(socket, &icqlink->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);
+      else
+        FD_SET(socket, &icqlink->TCP_writefds);
+    }
+
+    if(socket+1>icqlink->TCP_maxfd)
+      icqlink->TCP_maxfd=socket+1;
+  }
+
+  return 0; /* traverse the entire list */
+}
+
+/* helper function for icq_TCPMain */
+int _handle_ready_sockets(void *p, va_list data)
+{
+  icq_TCPLink *plink=(icq_TCPLink *)p;
+  ICQLINK *icqlink = plink->icqlink;
+  int socket=plink->socket;
+
+  (void)data;
+
+  /* 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)))
+    {
+      icq_TCPLinkOnConnect(plink);
+      return 0; 
+    }
+
+    if((time(0L) - plink->connect_time) > TCP_LINK_CONNECT_TIMEOUT)
+    {
+      icq_TCPLinkClose(plink);
+      return 0;
+    }
+  }
+
+  /* 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(plink->mode & TCP_LINK_MODE_LISTEN)
+      (void)icq_TCPLinkAccept(plink);
+    else {
+
+      int result=icq_TCPLinkOnDataReceived(plink);
+
+      /* close the link if there was a receive error or if *
+       * the remote end has closed the connection */
+      if (result < 1) 
+        icq_TCPLinkClose(plink);
+
+    }
+  }
+
+  return 0; /* traverse the entire list */
+}
+
+/* helper function for icq_TCPMain */
+int _process_links(void *p, va_list data)
+{
+  icq_TCPLink *plink=(icq_TCPLink *)p;
+
+  (void)data;
+
+  /* receive any packets watiting on the link */
+  icq_TCPLinkProcessReceived(plink);
+
+  /* if this a currently sending file link, send data! */
+  if(plink->type==TCP_LINK_FILE) {
+    icq_FileSession *psession=plink->session;
+    if(psession && psession->status==FILE_STATUS_SENDING)
+      icq_FileSessionSendData(psession);
+  }
+
+  return 0; /* traverse entire list */
+}
+
+void icq_TCPMain(ICQLINK *link)
+{
+  struct timeval tv;
+
+  tv.tv_sec = 0;
+  tv.tv_usec = 0;
+
+  link->TCP_maxfd = 0;
+  FD_ZERO(&link->TCP_readfds);
+  FD_ZERO(&link->TCP_writefds);
+
+  /* generate the fd sets for all open tcp links */
+  (void)list_traverse(link->icq_TCPLinks, _generate_fds);
+
+  /* determine which sockets require maintenance */
+  select(link->TCP_maxfd, &link->TCP_readfds, &link->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);
+
+  /* process all packets waiting for each TCPLink */
+  (void)list_traverse(link->icq_TCPLinks, _process_links, 0, 0);
+}
+
+icq_TCPLink *icq_TCPCheckLink(ICQLINK *link, DWORD uin, int type)
+{
+  icq_TCPLink *plink=icq_FindTCPLink(link, uin, type);
+
+  if(!plink)
+  {
+    plink=icq_TCPLinkNew( link );
+    if(type==TCP_LINK_MESSAGE)
+      icq_TCPLinkConnect(plink, uin, 0);
+  }
+
+  return plink;
+
+}
+
+DWORD icq_TCPSendMessage(ICQLINK *link, DWORD uin, const char *message)
+{
+  icq_TCPLink *plink;
+  icq_Packet *p;
+  DWORD sequence;
+  char data[512] ;
+  
+  strncpy(data,message,512) ;
+  icq_RusConv("kw", data) ;
+
+  plink=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE);
+
+  /* create and send the message packet */
+  p=icq_TCPCreateMessagePacket(plink, (unsigned char *)data);
+  sequence=icq_TCPLinkSendSeq(plink, p, 0);
+
+#ifdef TCP_PACKET_TRACE
+  printf("message packet sent to uin %lu { sequence=%lx }\n", uin, p->id);
+#endif
+
+  return sequence;
+}
+
+DWORD icq_TCPSendURL(ICQLINK *link, DWORD uin, const char *message, const char *url)
+{
+  icq_TCPLink *plink;
+  icq_Packet *p;
+  DWORD sequence;
+  char data[512];
+
+  plink=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE);
+  
+  strncpy(data, message, 512);
+  data[511] = '\0';
+  icq_RusConv("kw", data);
+
+  /* create and send the url packet */
+  p=icq_TCPCreateURLPacket(plink, data, url);
+  sequence=icq_TCPLinkSendSeq(plink, p, 0);
+
+#ifdef TCP_PACKET_TRACE
+  printf("url packet queued for uin %lu { sequence=%lx }\n", uin, p->id);
+#endif
+
+  return sequence;
+}
+
+DWORD icq_SendChatRequest(ICQLINK *link, DWORD uin, const char *message)
+{
+  icq_TCPLink *plink;
+  icq_Packet *p;
+  DWORD sequence;
+  char data[512];
+
+  plink=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE);
+  
+  strncpy(data, message, 512);
+  data[511] = '\0';
+  icq_RusConv("kw", data);
+
+  /* create and send the url packet */
+  p=icq_TCPCreateChatReqPacket(plink, (unsigned char *)data);
+  sequence=icq_TCPLinkSendSeq(plink, p, 0);
+
+#ifdef TCP_PACKET_TRACE
+  printf("chat req packet sent to uin %lu { sequence=%lx }\n", uin, p->id);
+#endif
+
+  return sequence;
+}
+
+unsigned long icq_SendFileRequest(ICQLINK *link, unsigned long uin,
+  const char *message, char **files)
+{
+  icq_TCPLink *plink;
+  icq_FileSession *pfile;
+  icq_Packet *p;
+  unsigned long sequence;
+  char filename[64];
+  char data[512];
+
+  plink=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE);
+
+  /* create the file session, this will be linked to the incoming icq_TCPLink
+   * in icq_HandleFileAck */ 
+  pfile=icq_FileSessionNew(link);
+  pfile->remote_uin=uin;
+  pfile->files=files;
+  pfile->direction=FILE_STATUS_SENDING;
+
+  /* count the number and size of the files */
+  pfile->total_files=0;
+  while(*files) {
+    struct stat file_status;
+
+    if(stat(*files, &file_status)==0) {
+      pfile->total_files++;
+      pfile->total_bytes+=file_status.st_size;
+    }
+    files++;
+  }
+
+  strncpy(filename, *(pfile->files), 64);
+
+  strncpy(data, message, 512);
+  data[511] = '\0';
+  icq_RusConv("kw", data);  
+
+  /* create and send the file req packet */
+  p=icq_TCPCreateFileReqPacket(plink, (char *)data, filename, 
+    pfile->total_bytes);
+  sequence=icq_TCPLinkSendSeq(plink, p, 0);
+  pfile->id=sequence;
+
+#ifdef TCP_PACKET_TRACE
+  printf("file req packet sent to uin %lu { sequence=%lx }\n", uin, p->id);
+#endif
+
+  return sequence;
+}            
+
+void icq_AcceptChatRequest(ICQLINK *link, DWORD uin, unsigned long sequence)
+{
+  icq_TCPLink *pmessage, *plisten;
+  icq_ChatSession *pchat;
+  icq_Packet *p;
+
+  pmessage=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE);
+
+  /* create the chat listening socket if necessary */
+  if(!(plisten=icq_FindTCPLink(link, 0, TCP_LINK_CHAT)))
+  {
+    plisten=icq_TCPLinkNew( link );
+    plisten->type=TCP_LINK_CHAT;
+    icq_TCPLinkListen(plisten);
+  }
+
+  /* create the chat session, this will be linked to the incoming icq_TCPLink
+   * in TCPProcessHello */ 
+  pchat=icq_ChatSessionNew(link);
+  pchat->id=sequence;
+  pchat->remote_uin=uin;
+
+  /* create and send the ack packet */
+  p=icq_TCPCreateChatReqAck(pmessage,
+    ntohs(plisten->socket_address.sin_port));
+  (void)icq_TCPLinkSendSeq(pmessage, p, sequence);
+
+#ifdef TCP_PACKET_TRACE
+  printf("chat req ack sent to uin %lu { sequence=%lx }\n", uin, sequence);
+#endif
+}
+
+void icq_TCPSendChatData(ICQLINK *link, DWORD uin, const char *data)
+{
+  icq_TCPLink *plink=icq_FindTCPLink(link, uin, TCP_LINK_CHAT);
+  char data1[512];
+  int data1_len;
+
+  if(!plink)
+    return;  
+
+  strncpy(data1,data,512) ;
+  data1[511] = '\0';
+  data1_len = strlen(data);
+  icq_ChatRusConv_n("kw", data1, data1_len);
+
+  send(plink->socket, data1, data1_len, 0);
+
+}
+
+void icq_TCPSendChatData_n(ICQLINK *link, DWORD uin, const char *data, int len)
+{
+  icq_TCPLink *plink=icq_FindTCPLink(link, uin, TCP_LINK_CHAT);
+  char *data1;
+
+  if(!plink)
+    return;
+
+  data1 = (char *)malloc(len);
+  memcpy(data1, data, len);
+  icq_ChatRusConv_n("kw", data1, len);  
+
+  send(plink->socket, data1, len, 0);
+
+}
+
+void icq_TCPCloseChat(ICQLINK *link, unsigned long uin)
+{
+  icq_TCPLink *plink=icq_FindTCPLink(link, uin, TCP_LINK_CHAT);
+
+  if(plink)
+    icq_TCPLinkClose(plink);
+
+}
+
+icq_FileSession *icq_AcceptFileRequest(ICQLINK *link, DWORD uin,
+  unsigned long sequence)
+{
+  icq_TCPLink *pmessage, *plisten;
+  icq_FileSession *pfile;
+  icq_Packet *p;
+
+  pmessage=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE);
+
+  /* create the file listening socket if necessary */
+  if(!(plisten=icq_FindTCPLink(link, 0, TCP_LINK_FILE)))
+  {
+    plisten=icq_TCPLinkNew( link );
+    plisten->type=TCP_LINK_FILE;
+    icq_TCPLinkListen(plisten);
+  }
+
+  /* create the file session, this will be linked to the incoming icq_TCPLink
+   * in TCPProcessHello */ 
+  pfile=icq_FileSessionNew(link);
+  pfile->id=sequence;
+  pfile->remote_uin=uin;
+  pfile->direction=FILE_STATUS_RECEIVING;
+  icq_FileSessionSetStatus(pfile, FILE_STATUS_LISTENING);
+
+  /* create and send the ack packet */
+  p=icq_TCPCreateFileReqAck(pmessage, 
+    ntohs(plisten->socket_address.sin_port));
+  (void)icq_TCPLinkSendSeq(pmessage, p, sequence);
+
+#ifdef TCP_PACKET_TRACE
+  printf("file req ack sent to uin %lu { sequence=%lx }\n", uin, sequence);
+#endif
+
+  return pfile;
+
+}
+
+void icq_RefuseFileRequest(ICQLINK *link, DWORD uin, 
+  unsigned long sequence, const char *reason)
+{
+  icq_TCPLink *pmessage=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE);
+  icq_Packet *p;
+
+  /* create and send the refuse packet */
+  p=icq_TCPCreateFileReqRefuse(pmessage,
+    ntohs(pmessage->socket_address.sin_port), reason);
+  (void)icq_TCPLinkSendSeq(pmessage, p, sequence);
+
+#ifdef TCP_PACKET_TRACE
+  printf("file req refuse sent to uin %lu { sequence=%lx, reason=\"%s\" }\n",
+    uin, sequence, reason);
+#endif
+
+}
+
+void icq_CancelFileRequest(ICQLINK *link, DWORD uin, unsigned long sequence)
+{
+  icq_TCPLink *pmessage=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE);
+  icq_FileSession *psession=icq_FindFileSession(link, uin, sequence);
+  icq_Packet *p;
+
+  if (psession)
+    icq_FileSessionClose(psession);
+
+  /* create and send the cancel packet */
+  p=icq_TCPCreateFileReqCancel(pmessage,
+    ntohs(pmessage->socket_address.sin_port));
+  (void)icq_TCPLinkSendSeq(pmessage, p, sequence);
+#ifdef TCP_PACKET_TRACE
+  printf("file req cancel sent to uin %lu { sequence=%lx }\n", uin, sequence);
+#endif
+
+}
+
+void icq_RefuseChatRequest(ICQLINK *link, DWORD uin, 
+  unsigned long sequence, const char *reason)
+{
+  icq_TCPLink *pmessage=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE);
+  icq_Packet *p;
+
+  /* create and send the refuse packet */
+  p=icq_TCPCreateChatReqRefuse(pmessage,
+    ntohs(pmessage->socket_address.sin_port), reason);
+  (void)icq_TCPLinkSendSeq(pmessage, p, sequence);
+
+#ifdef TCP_PACKET_TRACE
+  printf("chat req refuse sent to uin %lu { sequence=%lx, reason=\"%s\" }\n",
+    uin, sequence, reason);
+#endif
+
+}
+
+void icq_CancelChatRequest(ICQLINK *link, DWORD uin, unsigned long sequence)
+{
+  icq_TCPLink *pmessage=icq_TCPCheckLink(link, uin, TCP_LINK_MESSAGE);
+  icq_FileSession *psession=icq_FindFileSession(link, uin, sequence);
+  icq_Packet *p;
+
+  if (psession)
+    icq_FileSessionClose(psession);
+
+  /* create and send the cancel packet */
+  p=icq_TCPCreateChatReqCancel(pmessage,
+    ntohs(pmessage->socket_address.sin_port));
+  (void)icq_TCPLinkSendSeq(pmessage, p, sequence);
+
+#ifdef TCP_PACKET_TRACE
+  printf("chat req cancel sent to uin %lu { sequence=%lx }\n", uin, sequence);
+#endif
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/tcp.h	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,42 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+#ifndef _ICQTCP_H
+#define _ICQTCP_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "icq.h"
+#include "tcplink.h"
+#include "util.h"
+
+/* initialize icq_TCPSocket and icq_TCPSocketAddress
+ * returns < 0 on failure */
+int icq_TCPInit(ICQLINK *link);
+
+/* close icq_TCPSocket, internal cleanup */
+void icq_TCPDone(ICQLINK *link);
+
+int icq_TCPProcessHello(icq_Packet *p, icq_TCPLink *plink);
+void icq_TCPProcessPacket(icq_Packet *p, icq_TCPLink *plink);
+void icq_TCPProcessChatPacket(icq_Packet *p, icq_TCPLink *plink);
+void icq_TCPProcessFilePacket(icq_Packet *p, icq_TCPLink *plink);
+
+/* Debugging */
+/* trace packet process results */
+/* #define TCP_PROCESS_TRACE */
+
+/* trace sent and received icq packets */
+/* #define TCP_PACKET_TRACE     */
+
+/* trace raw sent and received packet data */
+/* #define TCP_RAW_TRACE  */
+
+/* trace recv buffer in tcplink.c*/
+#undef TCP_BUFFER_TRACE
+
+/* trace queueing operations in list.c */
+#undef TCP_QUEUE_TRACE
+
+#endif /* _ICQTCP_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/tcpchathandle.c	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,271 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+$Id: tcpchathandle.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Log$
+Revision 1.1  2000/11/28 02:22:42  warmenhoven
+icq. whoop de doo
+
+Revision 1.8  2000/07/24 03:10:08  bills
+added support for real nickname during TCP transactions like file and
+chat, instead of using Bill all the time (hmm, where'd I get that from? :)
+
+Revision 1.7  2000/07/09 22:19:35  bills
+added new *Close functions, use *Close functions instead of *Delete
+where correct, and misc cleanup
+
+Revision 1.6  2000/05/04 15:57:20  bills
+Reworked file transfer notification, small bugfixes, and cleanups.
+
+Revision 1.5  2000/05/03 18:29:15  denis
+Callbacks have been moved to the ICQLINK structure.
+
+Revision 1.4  2000/04/05 14:37:02  denis
+Applied patch from "Guillaume R." <grs@mail.com> for basic Win32
+compatibility.
+
+Revision 1.3  2000/02/07 02:54:45  bills
+warning cleanups.
+
+Revision 1.2  2000/02/07 02:43:37  bills
+new code for special chat functions (background, fonts, etc)
+
+Revision 1.1  1999/09/29 19:47:21  bills
+reworked chat/file handling.  fixed chat. (it's been broke since I put
+non-blocking connects in)
+
+*/
+
+#include <time.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#include <stdlib.h>
+
+#include "icqtypes.h"
+#include "icq.h"
+#include "icqlib.h"
+
+#include "stdpackets.h"
+#include "tcplink.h"
+#include "chatsession.h"
+
+void icq_HandleChatAck(icq_TCPLink *plink, icq_Packet *p, int port)
+{
+  icq_TCPLink *pchatlink;
+  icq_ChatSession *pchat;
+  icq_Packet *p2;
+
+  if(plink->icqlink->icq_RequestNotify)
+    (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_ACK, 0, 0);
+  pchatlink=icq_TCPLinkNew(plink->icqlink);
+  pchatlink->type=TCP_LINK_CHAT;
+  pchatlink->id=p->id;
+  
+  pchat=icq_ChatSessionNew(plink->icqlink);
+  pchat->id=p->id;
+  pchat->remote_uin=plink->remote_uin;
+  icq_ChatSessionSetStatus(pchat, CHAT_STATUS_CONNECTING);
+  icq_TCPLinkConnect(pchatlink, plink->remote_uin, port);
+
+  pchatlink->session=pchat;
+
+  p2=icq_TCPCreateChatInfoPacket(pchatlink, plink->icqlink->icq_Nick,
+    0x00ffffff, 0x00000000);
+  icq_TCPLinkSend(pchatlink, p2);
+
+}
+
+void icq_HandleChatHello(icq_TCPLink *plink)
+{
+
+  /* once the hello packet has been processed and we know which uin this
+   * link is for, we can link up with a chat session */
+  icq_ChatSession *pchat=icq_FindChatSession(plink->icqlink,
+    plink->remote_uin);
+
+  if(pchat)
+  {
+    plink->id=pchat->id;
+    plink->session=pchat;
+    icq_ChatSessionSetStatus(pchat, CHAT_STATUS_WAIT_NAME);
+
+  } else {
+
+    icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING,
+      "unexpected chat hello received from %d, closing link\n",
+      plink->remote_uin);
+    icq_TCPLinkClose(plink);
+  }
+
+}
+
+void icq_TCPOnChatReqReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id)
+{
+#ifdef TCP_PACKET_TRACE
+  printf("chat request packet received from %lu { sequence=%lx, message=%s }\n",
+     uin, id, message);
+#endif /* TCP_PACKET_TRACE */
+
+  if(link->icq_RecvChatReq) {
+
+    /* use the current system time for time received */
+    time_t t=time(0);
+    struct tm *ptime=localtime(&t);
+
+    (*link->icq_RecvChatReq)(link, uin, ptime->tm_hour, ptime->tm_min,
+       ptime->tm_mday, ptime->tm_mon+1, ptime->tm_year+1900, message, id);
+
+    /* don't send an acknowledgement to the remote client!
+     * GUI is responsible for sending acknowledgement once user accepts
+     * or denies using icq_TCPSendChatAck */
+  }
+}
+
+void icq_TCPChatUpdateFont(icq_TCPLink *plink, const char *font, WORD encoding, DWORD style, DWORD size)
+{
+  int packet_len, fontlen;
+  char *buffer;
+  if(!plink->icqlink->icq_RequestNotify)
+    return;
+  buffer = malloc(packet_len = (2 + (fontlen = strlen(font) + 1)) + 2 + 1 + (4+1)*2);
+  buffer[0] = '\x11';
+  *((DWORD *)&buffer[1]) = style;
+  buffer[5] = '\x12';
+  *((DWORD *)&buffer[6]) = size;
+  buffer[10] = '\x10';
+  *((WORD *)&buffer[11]) = fontlen;
+  strcpy(&buffer[13], font);
+  icq_RusConv("wk", &buffer[13]);
+  *((WORD *)&buffer[13 + fontlen]) = encoding;
+  if(plink->icqlink->icq_RequestNotify)
+    (*plink->icqlink->icq_RequestNotify)(plink->icqlink, plink->id, ICQ_NOTIFY_CHATDATA, packet_len, buffer);
+  free(buffer);
+}
+
+void icq_TCPChatUpdateColors(icq_TCPLink *plink, DWORD foreground, DWORD background)
+{
+  char buffer[10];
+
+  if(!plink->icqlink->icq_RequestNotify)
+    return;  
+  buffer[0] = '\x00';
+  *((DWORD *)&buffer[1]) = foreground;
+  buffer[5] = '\x01';
+  *((DWORD *)&buffer[6]) = background;
+  if(plink->icqlink->icq_RequestNotify)
+    (*plink->icqlink->icq_RequestNotify)(plink->icqlink, plink->id, ICQ_NOTIFY_CHATDATA,
+                                         sizeof(buffer), buffer);
+}
+
+void icq_TCPProcessChatPacket(icq_Packet *p, icq_TCPLink *plink)
+{
+  DWORD code;
+  DWORD remote_uin;
+  DWORD ip1, ip2;
+  DWORD fg, bg, fontstyle, fontsize;
+  WORD port1, encoding;
+  icq_Packet *presponse;
+  icq_ChatSession *pchat=(icq_ChatSession *)plink->session;
+  const char *font, *user;
+	
+  icq_PacketBegin(p);
+
+  code=icq_PacketRead32(p);
+  remote_uin=icq_PacketRead32(p);
+
+  if(code==0x00000006 || code==0x00070004)
+  {
+    font = (char *)NULL;
+    encoding = 0;
+    fontstyle = 0;
+    fontsize = 0;
+    if(code == 0x00070004)
+    {
+      ip1 = icq_PacketRead32(p);
+      ip2 = icq_PacketRead32(p);
+      icq_PacketRead8(p);
+      port1 = icq_PacketRead16(p);
+      fontsize = icq_PacketRead32(p);
+      fontstyle = icq_PacketRead32(p);
+      font = icq_PacketReadString(p);
+      encoding = icq_PacketRead16(p);
+    }
+    else
+    {
+      ip1 = icq_PacketRead32(p);
+      ip2 = icq_PacketRead32(p);
+      port1 = icq_PacketRead16(p);
+      icq_PacketRead8(p);
+      fontsize = icq_PacketRead32(p);
+      fontstyle = icq_PacketRead32(p);
+      font = icq_PacketReadString(p);
+      encoding = icq_PacketRead16(p);
+    }
+    if(font)
+      icq_TCPChatUpdateFont(plink, font, encoding, fontstyle, fontsize);
+    icq_ChatSessionSetStatus(pchat, CHAT_STATUS_READY);
+    plink->mode|=TCP_LINK_MODE_RAW;
+  }
+  else
+    if(remote_uin>0xffffff00)
+    {
+      remote_uin=icq_PacketRead32(p);
+      user = icq_PacketReadString(p);
+      icq_PacketRead16(p); /* Unknown */;
+      fg = icq_PacketRead32(p);
+      bg = icq_PacketRead32(p);
+      icq_TCPChatUpdateColors(plink, fg, bg);
+
+      presponse=icq_TCPCreateChatInfo2Packet(plink, plink->icqlink->icq_Nick,
+        0x00ffffff, 0x00000000);
+      icq_PacketSend(presponse, plink->socket);
+      icq_PacketDelete(presponse);
+      icq_ChatSessionSetStatus(pchat, CHAT_STATUS_WAIT_FONT);
+    }
+    else
+    {
+      user = icq_PacketReadString(p);
+      fg = icq_PacketRead32(p);
+      bg = icq_PacketRead32(p);
+      icq_TCPChatUpdateColors(plink, fg, bg);
+      font = (char *)NULL;
+      encoding = 0;
+      fontstyle = 0;
+      fontsize = 0;
+      if((code = icq_PacketRead32(p)) == 0x00070004)
+      {
+        icq_PacketRead32(p);
+        ip1 = icq_PacketRead32(p);
+        ip2 = icq_PacketRead32(p);
+        icq_PacketRead8(p);
+        port1 = icq_PacketRead16(p);
+        fontsize = icq_PacketRead32(p);
+        fontstyle = icq_PacketRead32(p);
+        font = icq_PacketReadString(p);
+        encoding = icq_PacketRead16(p);
+      }
+      else if(code == 0x00000006)
+      {
+        icq_PacketRead32(p);
+        ip1 = icq_PacketRead32(p);
+        ip2 = icq_PacketRead32(p);
+        port1 = icq_PacketRead16(p);
+        icq_PacketRead8(p);
+        fontsize = icq_PacketRead32(p);
+        fontstyle = icq_PacketRead32(p);
+        font = icq_PacketReadString(p);
+        encoding = icq_PacketRead16(p);
+      }
+      if(font)
+        icq_TCPChatUpdateFont(plink, font, encoding, fontstyle, fontsize);
+      presponse=icq_TCPCreateChatFontInfoPacket(plink);
+      icq_PacketSend(presponse, plink->socket);
+      icq_PacketDelete(presponse);
+      /* notify app that chat connection has been established */
+      icq_ChatSessionSetStatus(pchat, CHAT_STATUS_READY);
+      plink->mode|=TCP_LINK_MODE_RAW;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/tcpfilehandle.c	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,295 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+$Id: tcpfilehandle.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Log$
+Revision 1.1  2000/11/28 02:22:42  warmenhoven
+icq. whoop de doo
+
+Revision 1.15  2000/07/24 03:10:08  bills
+added support for real nickname during TCP transactions like file and
+chat, instead of using Bill all the time (hmm, where'd I get that from? :)
+
+Revision 1.14  2000/07/09 22:19:35  bills
+added new *Close functions, use *Close functions instead of *Delete
+where correct, and misc cleanup
+
+Revision 1.13  2000/06/25 16:35:08  denis
+'\n' was added at the end of log messages.
+
+Revision 1.12  2000/06/15 01:52:59  bills
+fixed bug: sending file sessions would freeze if remote side changed speed
+
+Revision 1.11  2000/05/04 15:57:20  bills
+Reworked file transfer notification, small bugfixes, and cleanups.
+
+Revision 1.10  2000/05/03 18:29:15  denis
+Callbacks have been moved to the ICQLINK structure.
+
+Revision 1.9  2000/04/10 18:11:45  denis
+ANSI cleanups.
+
+Revision 1.8  2000/04/10 16:36:04  denis
+Some more Win32 compatibility from Guillaume Rosanis <grs@mail.com>
+
+Revision 1.7  2000/04/05 14:37:02  denis
+Applied patch from "Guillaume R." <grs@mail.com> for basic Win32
+compatibility.
+
+Revision 1.6  2000/01/20 20:06:00  bills
+removed debugging printfs
+
+Revision 1.5  2000/01/20 19:59:15  bills
+first implementation of sending file requests
+
+Revision 1.4  2000/01/16 21:29:31  bills
+added code so icq_FileSessions now keep track of the tcplink to which
+they are attached
+
+Revision 1.3  1999/12/21 00:30:15  bills
+added more file transfer logic to write file to disk
+
+Revision 1.2  1999/11/30 09:47:04  bills
+added icq_HandleFileHello
+
+Revision 1.1  1999/09/29 19:47:21  bills
+reworked chat/file handling.  fixed chat. (it's been broke since I put
+non-blocking connects in)
+
+*/
+
+#include <time.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#ifdef _MSVC_
+#include <io.h>
+#define open _open
+#define close _close
+#define read _read
+#define write _write
+#endif
+
+#include <errno.h>
+
+#include "icqtypes.h"
+#include "icq.h"
+#include "icqlib.h"
+
+#include "tcp.h"
+#include "icqpacket.h"
+#include "stdpackets.h"
+#include "tcplink.h"
+#include "filesession.h"
+
+void icq_TCPOnFileReqReceived(ICQLINK *link, DWORD uin, const char *message, 
+   const char *filename, unsigned long filesize, DWORD id)
+{
+#ifdef TCP_PACKET_TRACE
+  printf("file request packet received from %lu { sequence=%lx, message=%s }\n",
+     uin, id, message);
+#endif
+
+  if(link->icq_RecvFileReq) {
+
+    /* use the current system time for time received */
+    time_t t=time(0);
+    struct tm *ptime=localtime(&t);
+
+    (*link->icq_RecvFileReq)(link, uin, ptime->tm_hour, ptime->tm_min,
+       ptime->tm_mday, ptime->tm_mon+1, ptime->tm_year+1900, message, 
+       filename, filesize, id);
+
+    /* don't send an acknowledgement to the remote client!
+     * GUI is responsible for sending acknowledgement once user accepts
+     * or denies using icq_TCPSendFileAck */
+  }
+}
+
+void icq_TCPProcessFilePacket(icq_Packet *p, icq_TCPLink *plink)
+{
+  icq_FileSession *psession=(icq_FileSession *)plink->session;
+  BYTE type;
+  DWORD num_files;
+  DWORD total_bytes;
+  DWORD speed;
+  DWORD filesize;
+  const char *name;
+  int result;
+
+  icq_Packet *presponse;
+
+  icq_PacketBegin(p);
+
+  type=icq_PacketRead8(p);
+
+  switch(type)
+  {
+    case 0x00:
+      (void)icq_PacketRead32(p);
+      num_files=icq_PacketRead32(p);
+      total_bytes=icq_PacketRead32(p);
+      speed=icq_PacketRead32(p);
+      name=icq_PacketReadString(p);
+      psession->total_files=num_files;
+      psession->total_bytes=total_bytes;
+      psession->current_speed=speed;
+      icq_FileSessionSetHandle(psession, name);
+      icq_FileSessionSetStatus(psession, FILE_STATUS_INITIALIZED);
+
+      /* respond */
+      presponse=icq_TCPCreateFile01Packet(speed, plink->icqlink->icq_Nick);
+
+      icq_TCPLinkSend(plink, presponse);
+#ifdef TCP_PACKET_TRACE
+      printf("file 01 packet sent to uin %lu\n", plink->remote_uin);
+#endif
+
+      break;
+
+    case 0x01:
+      speed=icq_PacketRead32(p);
+      name=icq_PacketReadString(p);
+      psession->current_speed=speed;
+      icq_FileSessionSetHandle(psession, name);
+      icq_FileSessionSetStatus(psession, FILE_STATUS_INITIALIZED);
+
+      /* respond */
+      icq_FileSessionPrepareNextFile(psession);
+      presponse=icq_TCPCreateFile02Packet(psession->current_file,
+        psession->current_file_size, psession->current_speed);
+
+      icq_TCPLinkSend(plink, presponse);
+#ifdef TCP_PACKET_TRACE
+      printf("file 02 packet sent to uin %lu\n", plink->remote_uin);
+#endif       
+      break;
+
+    case 0x02:
+      /* when files are skipped
+      psession->total_transferred_bytes+=
+        (psession->current_file_size-psession->current_file_progress);
+      */
+
+      (void)icq_PacketRead8(p);
+      name=icq_PacketReadString(p);
+      (void)icq_PacketReadString(p);
+      filesize=icq_PacketRead32(p);
+      (void)icq_PacketRead32(p);
+      speed=icq_PacketRead32(p);
+      icq_FileSessionSetCurrentFile(psession, name);
+      psession->current_file_size=filesize;
+      psession->current_speed=speed;
+      psession->current_file_num++;
+      icq_FileSessionSetStatus(psession, FILE_STATUS_NEXT_FILE);
+
+      /* respond */
+      presponse=icq_TCPCreateFile03Packet(psession->current_file_progress,
+         speed);
+
+      icq_TCPLinkSend(plink, presponse);
+#ifdef TCP_PACKET_TRACE
+      printf("file 03 packet sent to uin %lu\n", plink->remote_uin);
+#endif       
+      break;
+
+    case 0x03:
+      filesize=icq_PacketRead32(p);
+      (void)icq_PacketRead32(p);       
+      speed=icq_PacketRead32(p);
+      psession->current_file_progress=filesize;
+      psession->total_transferred_bytes+=filesize;
+      psession->current_speed=speed;
+
+      icq_FileSessionSetStatus(psession, FILE_STATUS_NEXT_FILE);
+      icq_FileSessionSetStatus(psession, FILE_STATUS_SENDING);
+      break;
+
+    case 0x04:
+      (void)icq_PacketRead32(p);
+      icq_FileSessionSetStatus(psession, FILE_STATUS_STOP_FILE);
+      break;
+
+    case 0x05:
+      speed=icq_PacketRead32(p);
+      psession->current_speed=speed;
+      if(plink->icqlink->icq_RequestNotify)
+        (*plink->icqlink->icq_RequestNotify)(plink->icqlink, plink->id,
+          ICQ_NOTIFY_FILE, FILE_STATUS_NEW_SPEED, 0);   
+      break;
+
+    case 0x06:
+      if(plink->icqlink->icq_RequestNotify)
+        (*plink->icqlink->icq_RequestNotify)(plink->icqlink, plink->id, ICQ_NOTIFY_FILEDATA,
+                           p->length-sizeof(BYTE), p->data+sizeof(BYTE));
+      icq_FileSessionSetStatus(psession, FILE_STATUS_RECEIVING);
+      result=write(psession->current_fd, p->data+sizeof(BYTE), p->length-sizeof(BYTE));
+      psession->current_file_progress+=p->length-sizeof(BYTE);
+      psession->total_transferred_bytes+=p->length-sizeof(BYTE);
+      break;
+
+    default:
+      icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "unknown file packet type %d!\n", type);
+
+  }
+}
+
+void icq_HandleFileHello(icq_TCPLink *plink)
+{
+
+  /* once the hello packet has been processed and we know which uin this
+   * link is for, we can link up with a file session */
+  icq_FileSession *pfile=icq_FindFileSession(plink->icqlink,
+    plink->remote_uin, 0);
+
+  if(pfile)
+  {
+    plink->id=pfile->id;
+    plink->session=pfile;
+    pfile->tcplink=plink;
+    icq_FileSessionSetStatus(pfile, FILE_STATUS_CONNECTED);
+
+  } else {
+
+    icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING,
+      "unexpected file hello received from %d, closing link\n",
+      plink->remote_uin);
+    icq_TCPLinkClose(plink);
+  }
+
+}
+  
+void icq_HandleFileAck(icq_TCPLink *plink, icq_Packet *p, int port)
+{
+  icq_TCPLink *pfilelink;
+  icq_FileSession *pfile;
+  icq_Packet *p2;
+
+  if(plink->icqlink->icq_RequestNotify)
+    (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_ACK, 0, 0);
+  pfilelink=icq_TCPLinkNew(plink->icqlink);
+  pfilelink->type=TCP_LINK_FILE;
+  pfilelink->id=p->id;
+
+  /* once the ack packet has been processed, link up with the file session */
+  pfile=icq_FindFileSession(plink->icqlink, plink->remote_uin, 0);
+
+  pfile->tcplink=pfilelink;
+  pfilelink->id=pfile->id;
+
+  if (plink->icqlink->icq_RequestNotify)
+    (*plink->icqlink->icq_RequestNotify)(plink->icqlink, pfile->id, 
+      ICQ_NOTIFY_FILESESSION, sizeof(icq_FileSession), pfile);
+  
+  icq_FileSessionSetStatus(pfile, FILE_STATUS_CONNECTING);
+  icq_TCPLinkConnect(pfilelink, plink->remote_uin, port);
+
+  pfilelink->session=pfile;
+
+  p2=icq_TCPCreateFile00Packet( pfile->total_files,
+    pfile->total_bytes, pfile->current_speed, plink->icqlink->icq_Nick);
+  icq_TCPLinkSend(pfilelink, p2);
+
+}   
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/tcphandle.c	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,366 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+$Id: tcphandle.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Log$
+Revision 1.1  2000/11/28 02:22:42  warmenhoven
+icq. whoop de doo
+
+Revision 1.12  2000/07/09 22:19:35  bills
+added new *Close functions, use *Close functions instead of *Delete
+where correct, and misc cleanup
+
+Revision 1.11  2000/06/25 16:36:16  denis
+'\n' was added at the end of log messages.
+
+Revision 1.10  2000/05/04 15:57:20  bills
+Reworked file transfer notification, small bugfixes, and cleanups.
+
+Revision 1.9  2000/05/03 18:29:15  denis
+Callbacks have been moved to the ICQLINK structure.
+
+Revision 1.8  2000/04/05 14:37:02  denis
+Applied patch from "Guillaume R." <grs@mail.com> for basic Win32
+compatibility.
+
+Revision 1.7  2000/01/20 20:06:00  bills
+removed debugging printfs
+
+Revision 1.6  2000/01/20 19:59:15  bills
+first implementation of sending file requests
+
+Revision 1.5  1999/11/30 09:51:42  bills
+more file xfer logic added
+
+Revision 1.4  1999/11/11 15:10:30  guruz
+- Added Base for Webpager Messages. Please type "make fixme"
+- Removed Segfault when kicq is started the first time
+
+Revision 1.3  1999/10/01 02:28:51  bills
+icq_TCPProcessHello returns something now :)
+
+Revision 1.2  1999/10/01 00:49:20  lord
+some compilation problems are fixed.
+
+Revision 1.1  1999/09/29 19:47:21  bills
+reworked chat/file handling.  fixed chat. (it's been broke since I put
+non-blocking connects in)
+
+Revision 1.15  1999/07/16 15:45:59  denis
+Cleaned up.
+
+Revision 1.14  1999/07/16 12:10:10  denis
+tcp_packet* functions renamed to icq_Packet*
+Cleaned up.
+
+Revision 1.13  1999/07/12 15:13:41  cproch
+- added definition of ICQLINK to hold session-specific global variabled
+  applications which have more than one connection are now possible
+- changed nearly every function defintion to support ICQLINK parameter
+
+Revision 1.12  1999/06/30 13:51:25  bills
+cleanups
+
+Revision 1.11  1999/05/03 21:41:30  bills
+initial file xfer support added- untested
+
+Revision 1.10  1999/04/29 09:36:06  denis
+Cleanups, warning removed
+
+Revision 1.9  1999/04/17 19:40:33  bills
+reworked code to use icq_TCPLinks instead of icq_ContactItem entries.
+modified ProcessChatPacket to negotiate both sending and receiving chat
+requests properly.
+
+Revision 1.8  1999/04/14 15:12:02  denis
+Cleanups for "strict" compiling (-ansi -pedantic)
+icq_ContactItem parameter added to function icq_TCPOnMessageReceived()
+Segfault fixed on spoofed messages.
+
+*/
+
+#include <time.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#include "icqtypes.h"
+#include "icq.h"
+#include "icqlib.h"
+
+#include "tcp.h"
+#include "stdpackets.h"
+#include "tcplink.h"
+
+void icq_TCPOnMessageReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id, icq_TCPLink *plink);
+void icq_TCPOnURLReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id);
+void icq_TCPOnChatReqReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id);
+void icq_TCPOnFileReqReceived(ICQLINK *link, DWORD uin, const char *message, 
+   const char *filename, unsigned long filesize, DWORD id);
+void icq_TCPProcessAck(ICQLINK *link, icq_Packet *p);
+void icq_HandleChatAck(icq_TCPLink *plink, icq_Packet *p, int port);
+void icq_HandleChatHello(icq_TCPLink *plink);
+void icq_HandleFileHello(icq_TCPLink *plink);
+void icq_HandleFileAck(icq_TCPLink *plink, icq_Packet *p, int port);
+
+void icq_TCPProcessPacket(icq_Packet *p, icq_TCPLink *plink)
+{
+  DWORD uin;
+  WORD version;
+  WORD command;
+  WORD type;
+  WORD status;
+  DWORD command_type;
+  DWORD filesize = 0;
+  DWORD port = 0;
+  
+  const char *message;
+  const char *filename = 0;
+
+  icq_PacketBegin(p);
+  (void)icq_PacketRead32(p);
+  version=icq_PacketRead16(p);
+  command=icq_PacketRead16(p);
+  (void)icq_PacketRead16(p);
+
+  uin=icq_PacketRead32(p);
+  type=icq_PacketRead16(p);
+  message=icq_PacketReadString(p);
+  (void)icq_PacketRead32(p);
+  (void)icq_PacketRead32(p);
+  (void)icq_PacketRead32(p);
+  (void)icq_PacketRead8(p);
+  status=icq_PacketRead16(p);
+  command_type=icq_PacketRead16(p);
+
+  switch(type)
+  {
+    case ICQ_TCP_MSG_MSG:
+    case ICQ_TCP_MSG_URL:
+      p->id=icq_PacketRead32(p);
+      break;
+
+    case ICQ_TCP_MSG_CHAT:
+      (void)icq_PacketReadString(p);
+      (void)icq_PacketRead16(p);
+      (void)icq_PacketRead16(p);
+      port=icq_PacketRead32(p);
+      p->id=icq_PacketRead32(p);
+      break;
+
+    case ICQ_TCP_MSG_FILE:
+      (void)icq_PacketRead16(p);
+      (void)icq_PacketRead16(p);
+      filename=icq_PacketReadString(p);
+      filesize=icq_PacketRead32(p);
+      port=icq_PacketRead32(p);
+      p->id=icq_PacketRead32(p);
+      break;
+
+    default:
+      icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "unknown message packet, type %x\n", type);
+  }
+
+#ifdef TCP_PROCESS_TRACE
+  printf("packet processed from uin: %lu:\n", uin);
+  printf("   command: %x\ttype: %x\n", command, type);
+  printf("   status: %x\tcommand_type: %x\n", status, (int)command_type);
+  printf("   message %s\n", message);
+  printf("   id: %x\n", (int)p->id);
+#endif
+
+  switch(command)
+  {
+    case ICQ_TCP_MESSAGE:
+      switch(type)
+      {
+        case ICQ_TCP_MSG_MSG:
+          icq_TCPOnMessageReceived(plink->icqlink, uin, message, p->id, plink);
+          break;
+
+        case ICQ_TCP_MSG_URL:
+          icq_TCPOnURLReceived(plink->icqlink, uin, message, p->id);
+          break;
+
+        case ICQ_TCP_MSG_CHAT:
+          icq_TCPOnChatReqReceived(plink->icqlink, uin, message, p->id);
+          break;
+
+        case ICQ_TCP_MSG_FILE:
+          icq_TCPOnFileReqReceived(plink->icqlink, uin, message, filename, filesize, p->id);
+          break;
+
+        default:
+          icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "unknown message type %d!\n", type);
+          break;
+      }
+      break;
+
+    case ICQ_TCP_ACK:
+      switch(type) {
+        case ICQ_TCP_MSG_CHAT:
+          icq_HandleChatAck(plink, p, port);
+          break;
+
+        case ICQ_TCP_MSG_FILE:
+          icq_HandleFileAck(plink, p, port);
+          break;
+
+        case ICQ_TCP_MSG_MSG:
+        case ICQ_TCP_MSG_URL:
+          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:
+      /* icq_TCPProcessCancel(p); */
+      break;
+
+    default:
+      icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, 
+			  "unknown packet command %d!\n", command);
+  }
+}
+
+void icq_TCPProcessCancel(icq_Packet *p)
+{
+  (void)p;
+
+/*
+  find packet in queue
+  call notification function
+  remove packet from queue
+*/
+}
+
+int icq_TCPProcessHello(icq_Packet *p, icq_TCPLink *plink)
+{	
+  /* TCP Hello packet */
+  BYTE code;                /* 0xFF - init packet code */
+  DWORD version;            /* tcp version */
+  DWORD remote_port;        /* remote message listen port */
+  DWORD remote_uin;         /* remote uin */
+  DWORD remote_ip;          /* remote IP as seen by ICQ server */
+  DWORD remote_real_ip;     /* remote IP as seen by client */
+  BYTE flags;               /* tcp flags */
+  DWORD remote_other_port;  /* remote chat or file listen port */
+
+  icq_PacketBegin(p);
+  
+  code=icq_PacketRead8(p);
+  version=icq_PacketRead32(p);
+
+  if (!(p->length>=26 && code==ICQ_TCP_HELLO))
+  {
+    icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, 
+      "malformed hello packet received from %s:%d, closing link\n",
+      inet_ntoa(*((struct in_addr *)(&(plink->remote_address.sin_addr)))),
+      ntohs(plink->remote_address.sin_port));
+
+    icq_TCPLinkClose(plink);
+    return 0;
+  }
+  remote_port=icq_PacketRead32(p);
+  remote_uin=icq_PacketRead32(p);
+  remote_ip=icq_PacketRead32(p);
+  remote_real_ip=icq_PacketRead32(p);
+  flags=icq_PacketRead8(p);
+  remote_other_port=icq_PacketRead32(p);
+
+  icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, 
+    "hello packet received from %lu { version=%d }\n", remote_uin, version);
+
+  plink->remote_version=version;
+  plink->remote_uin=remote_uin;
+  plink->flags=flags;
+  plink->mode&=~TCP_LINK_MODE_HELLOWAIT;
+
+  /* file and chat sessions require additional handling */
+  if(plink->type==TCP_LINK_CHAT) icq_HandleChatHello(plink);
+  if(plink->type==TCP_LINK_FILE) icq_HandleFileHello(plink);
+
+  return 1;
+}
+
+void icq_TCPOnMessageReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id, icq_TCPLink *plink)
+{
+  char data[512] ;
+#ifdef TCP_PACKET_TRACE
+  printf("tcp message packet received from %lu { sequence=%x }\n",
+         uin, (int)id);
+#endif
+
+  if(link->icq_RecvMessage)
+  {
+    /* use the current system time for time received */
+    time_t t=time(0);
+    struct tm *ptime=localtime(&t);
+    icq_Packet *pack;
+    icq_TCPLink *preallink=icq_FindTCPLink(link, uin, TCP_LINK_MESSAGE);
+
+    strncpy(data,message,512) ;
+    icq_RusConv("wk",data) ;
+
+    (*link->icq_RecvMessage)(link, uin, ptime->tm_hour, ptime->tm_min,
+      ptime->tm_mday, ptime->tm_mon+1, ptime->tm_year+1900, data);
+
+    if(plink != preallink)
+    {
+/*      if(icq_SpoofedMessage)
+        (*icq_SpoofedMessage(uin, ...));*/
+    }
+
+    if(plink)
+    {
+      /* send an acknowledgement to the remote client */
+      pack=icq_TCPCreateMessageAck(plink,0);
+      icq_PacketAppend32(pack, id);
+      icq_PacketSend(pack, plink->socket);
+#ifdef TCP_PACKET_TRACE
+      printf("tcp message ack sent to uin %lu { sequence=%lx }\n", uin, id);
+#endif
+      icq_PacketDelete(pack);
+    }
+  }
+}
+
+void icq_TCPOnURLReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id)
+{
+#ifdef TCP_PACKET_TRACE
+  printf("tcp url packet received from %lu { sequence=%lx }\n",
+     uin, id);
+#endif /*TCP_PACKET_TRACE*/
+
+  if(link->icq_RecvURL) {
+
+    /* use the current system time for time received */
+    time_t t=time(0);
+    struct tm *ptime=localtime(&t);
+    icq_Packet *pack;
+    char *pfe;
+    icq_TCPLink *plink=icq_FindTCPLink(link, uin, TCP_LINK_MESSAGE);
+
+    /* the URL is split from the description by 0xFE */
+    pfe=strchr(message, '\xFE');
+    *pfe=0;
+    (*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);
+
+    /* send an acknowledgement to the remote client */
+    pack=icq_TCPCreateURLAck(plink,0);
+    icq_PacketAppend32(pack, id);
+    icq_PacketSend(pack, plink->socket);
+#ifdef TCP_PACKET_TRACE
+    printf("tcp message ack sent to %lu { sequence=%lx }\n", uin, id);
+#endif
+    icq_PacketDelete(pack);
+  }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/tcplink.c	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,1014 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+$Id: tcplink.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Log$
+Revision 1.1  2000/11/28 02:22:42  warmenhoven
+icq. whoop de doo
+
+Revision 1.38  2000/07/09 22:19:35  bills
+added new *Close functions, use *Close functions instead of *Delete
+where correct, and misc cleanup
+
+Revision 1.37  2000/06/15 01:53:17  bills
+added icq_TCPLinkSendSeq function
+
+Revision 1.36  2000/05/04 15:57:20  bills
+Reworked file transfer notification, small bugfixes, and cleanups.
+
+Revision 1.35  2000/05/03 18:29:15  denis
+Callbacks have been moved to the ICQLINK structure.
+
+Revision 1.34  2000/04/10 18:11:45  denis
+ANSI cleanups.
+
+Revision 1.33  2000/04/10 16:36:04  denis
+Some more Win32 compatibility from Guillaume Rosanis <grs@mail.com>
+
+Revision 1.32  2000/04/05 14:37:02  denis
+Applied patch from "Guillaume R." <grs@mail.com> for basic Win32
+compatibility.
+
+Revision 1.31  2000/02/15 04:00:16  bills
+ new icq_ChatRusConv_n function
+
+Revision 1.30  2000/02/07 02:46:29  bills
+implemented non-blocking TCP connects over SOCKS, cyrillic translation for chat
+
+Revision 1.29  2000/01/20 19:59:35  bills
+fixed bug in icq_TCPLinkConnect that caused file/chat connection attempts
+to go to the wrong port
+
+Revision 1.28  2000/01/16 03:59:10  bills
+reworked list code so list_nodes don't need to be inside item structures,
+removed strlist code and replaced with generic list calls
+
+Revision 1.27  1999/12/27 16:13:29  bills
+fixed bug in icq_TCPOnDataReceived, removed flags variable ;)
+
+Revision 1.26  1999/12/27 10:56:10  denis
+Unused "flags" variable commented out.
+
+Revision 1.25  1999/12/21 00:30:53  bills
+added icq_TCPLinkProcessReceived to support processing receive queue
+before delete (packets used to get dropped in this instance, oops),
+reworked icq_TCPLinkOnDataReceived to handle quick, large streams of data,
+changed icq_TCPLinkOnConnect and *Accept to make all sockets non-blocking.
+
+Revision 1.24  1999/12/14 03:33:34  bills
+icq_TCPLinkConnect now uses real_ip when our IP is same as remote IP to make
+connection, added code to implement connect timeout
+
+Revision 1.23  1999/11/30 09:57:44  bills
+buffer overflow check added, tcplinks will now close if buffer overflows.
+increased icq_TCPLinkBufferSize to 4096 to support file transfer packets
+
+Revision 1.22  1999/11/29 17:15:51  denis
+Absence of socklen_t type fixed.
+
+Revision 1.21  1999/10/01 00:49:21  lord
+some compilation problems are fixed.
+
+Revision 1.20  1999/09/29 20:26:41  bills
+ack forgot the args :)
+
+Revision 1.19  1999/09/29 20:21:45  bills
+renamed denis' new function
+
+Revision 1.18  1999/09/29 20:11:29  bills
+renamed tcp_link* to icq_TCPLink*.  many cleanups, added icq_TCPLinkOnConnect
+
+Revision 1.17  1999/09/29 17:10:05  denis
+TCP code SOCKS-ification. Not finished.
+
+Revision 1.16  1999/07/18 20:21:34  bills
+fixed fail notification bug introduced during ICQLINK changes, changed to
+use new byte-order functions & contact list functions, added better log
+messages
+
+Revision 1.15  1999/07/16 15:45:57  denis
+Cleaned up.
+
+Revision 1.14  1999/07/16 12:02:58  denis
+tcp_packet* functions renamed to icq_Packet*
+Cleaned up.
+
+Revision 1.13  1999/07/12 15:13:36  cproch
+- added definition of ICQLINK to hold session-specific global variabled
+  applications which have more than one connection are now possible
+- changed nearly every function defintion to support ICQLINK parameter
+
+Revision 1.12  1999/07/03 06:33:51  lord
+. byte order conversion macros added
+. some compilation warnings removed
+
+Revision 1.11  1999/06/30 13:52:23  bills
+implemented non-blocking connects
+
+Revision 1.10  1999/05/03 21:39:41  bills
+removed exit calls
+
+Revision 1.9  1999/04/29 09:35:54  denis
+Cleanups, warning removed
+
+Revision 1.8  1999/04/17 19:34:49  bills
+fixed bug in icq_TCPLinkOnDataReceived, multiple packets that come in on
+one recv call are now handled correctly.  added icq_TCPLinkAccept and
+icq_TCPLinkListen.  started using mode and type structure entries.  added
+icq_TCPLinks list and icq_FindTCPLink function.  changed received_queue and
+send_queue to lists.
+
+Revision 1.7  1999/04/14 15:02:45  denis
+Cleanups for "strict" compiling (-ansi -pedantic)
+
+Revision 1.6  1999/04/05 18:47:17  bills
+initial chat support implemented
+
+Revision 1.5  1999/03/31 01:50:54  bills
+wrapped up many tcp details- tcp code now handles incoming and outgoing
+tcp messages and urls!
+
+Revision 1.4  1999/03/28 03:27:49  bills
+fixed icq_TCPLinkConnect so it really connects to remote ip instead of
+always my local test computer O:)
+
+Revision 1.3  1999/03/26 20:02:41  bills
+fixed C++ comments, cleaned up
+
+Revision 1.2  1999/03/25 22:21:59  bills
+added necessary includes
+
+Revision 1.1  1999/03/25 21:09:07  bills
+tcp link functions
+*/
+
+#include <stdlib.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#include <fcntl.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#ifdef _WIN32
+#include <winsock.h>
+#define EINPROGRESS   WSAEINPROGRESS
+#define ENETUNREACH   WSAENETUNREACH
+#define ECONNREFUSED  WSAECONNREFUSED
+#define ETIMEDOUT     WSAETIMEDOUT
+#define EOPNOTSUPP    WSAEOPNOTSUPP
+#define EAFNOSUPPORT  WSAEAFNOSUPPORT
+#define EWOULDBLOCK   WSAEWOULDBLOCK
+#else
+#include <sys/socket.h>
+#include <netdb.h>
+#endif
+
+#include "icqtypes.h"
+#include "icq.h"
+#include "icqlib.h"
+#include "tcplink.h"
+#include "stdpackets.h"
+#include "util.h"
+#include "tcp.h"
+#include "errno.h"
+#include "chatsession.h"
+#include "filesession.h"
+
+icq_TCPLink *icq_TCPLinkNew(ICQLINK *link)
+{
+  icq_TCPLink *p=(icq_TCPLink *)malloc(sizeof(icq_TCPLink));
+
+  p->socket=-1;
+  p->icqlink=link;
+  p->mode=0;
+  p->session=0L;
+  p->type=TCP_LINK_MESSAGE;
+  p->buffer_count=0;
+  p->send_queue=list_new();
+  p->received_queue=list_new();
+  p->id=0;
+  p->remote_uin=0;
+  p->remote_version=0;
+  p->flags=0;
+  p->proxy_status = 0;
+
+  if(p)
+    list_enqueue(link->icq_TCPLinks, p);
+
+  return p;
+}
+
+int _icq_TCPLinkDelete(void *pv, va_list data)
+{
+  icq_Packet *p=(icq_Packet *)pv;
+  ICQLINK *icqlink=va_arg(data, ICQLINK *);
+
+  /* notify the app the packet didn't make it */
+  if(p->id)
+    (*icqlink->icq_RequestNotify)(icqlink, p->id, ICQ_NOTIFY_FAILED, 0, 0);
+
+  return 0;
+}
+
+void icq_TCPLinkDelete(void *pv)
+{
+  icq_TCPLink *p=(icq_TCPLink *)pv;
+
+  /* process anything left in the received queue */
+  icq_TCPLinkProcessReceived(p);
+
+  /* make sure we notify app that packets in send queue didn't make it */
+  (void)list_traverse(p->send_queue, _icq_TCPLinkDelete, p->icqlink);
+
+  /* destruct all packets still waiting on queues */
+  list_delete(p->send_queue, icq_PacketDelete);
+  list_delete(p->received_queue, icq_PacketDelete);
+
+  /* notify app if this was a chat or file xfer session and there is an
+   * id assigned */
+  if((p->type==TCP_LINK_CHAT || p->type==TCP_LINK_FILE) && p->id)
+    if(p->icqlink->icq_RequestNotify)
+      (*p->icqlink->icq_RequestNotify)(p->icqlink, p->id, ICQ_NOTIFY_SUCCESS, 0, 0);
+
+  /* if this is a chat or file link, delete the associated session as
+   * well, but make sure we unassociate ourself first so the session
+   * doesn't try to close us */
+  if(p->session)
+  {
+    if(p->type==TCP_LINK_CHAT)
+    {
+      icq_ChatSession *psession=p->session;
+      /*psession->tcplink=0L;*/
+      icq_ChatSessionClose(psession);
+    }
+
+    if(p->type==TCP_LINK_FILE) {
+      icq_FileSession *psession=p->session;
+      psession->tcplink=0L;
+      icq_FileSessionClose(psession);
+    }
+  }
+
+  /* close the socket after we notify app so app can read errno if necessary */
+  if (p->socket > -1)
+  {
+#ifdef _WIN32
+    closesocket(p->socket);
+#else
+    close(p->socket);
+#endif
+  }
+
+  free(p);
+}
+
+void icq_TCPLinkClose(icq_TCPLink *plink)
+{
+  list_remove(plink->icqlink->icq_TCPLinks, plink);
+  icq_TCPLinkDelete(plink);
+}
+
+int icq_TCPLinkProxyConnect(icq_TCPLink *plink, DWORD uin, int port)
+{
+  struct sockaddr_in prsin;
+  struct hostent *host_struct;
+  int conct;
+
+  (void)uin; (void)port;
+
+  prsin.sin_addr.s_addr = htonl(plink->icqlink->icq_ProxyIP);
+  if(prsin.sin_addr.s_addr  == (unsigned long)-1)
+  {
+    prsin.sin_addr.s_addr = inet_addr(plink->icqlink->icq_ProxyHost);
+    if(prsin.sin_addr.s_addr  == (unsigned long)-1) /* name isn't n.n.n.n so must be DNS */
+    {
+      host_struct = gethostbyname(plink->icqlink->icq_ProxyHost);
+      if(host_struct == 0L)
+      {
+        icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Can't find hostname: %s\n",
+                   plink->icqlink->icq_ProxyHost);
+        return -1;
+      }
+      prsin.sin_addr = *((struct in_addr *)host_struct->h_addr);
+    }
+  }
+  prsin.sin_family = AF_INET; /* we're using the inet not appletalk*/
+  prsin.sin_port = htons(plink->icqlink->icq_ProxyPort); /* port */
+/*   flags = fcntl(plink->socket, F_GETFL, 0); */
+/*   fcntl(plink->socket, F_SETFL, flags & (~O_NONBLOCK)); */
+  plink->mode |= TCP_LINK_SOCKS_CONNECTING;
+  conct = connect(plink->socket, (struct sockaddr *) &prsin, sizeof(prsin));
+  if(conct == -1) /* did we connect ?*/
+  {
+    if(errno != EINPROGRESS)
+    {
+      conct = errno;
+      icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Connection refused\n");
+      return conct;
+    }
+    return 1;
+  }
+  return 0;
+}
+
+int icq_TCPLinkProxyRequestAuthorization(icq_TCPLink *plink)
+{
+  char buf[1024];
+
+  plink->mode = (plink->mode & (~TCP_LINK_SOCKS_CONNECTING));
+  buf[0] = 5; /* protocol version */
+  buf[1] = 1; /* number of methods */
+  if(!strlen(plink->icqlink->icq_ProxyName) || !strlen(plink->icqlink->icq_ProxyPass) ||
+     !plink->icqlink->icq_ProxyAuth)
+  {
+    buf[2] = 0; /* no authorization required */
+    plink->mode |= TCP_LINK_SOCKS_NOAUTHSTATUS;
+  }
+  else
+  {
+    buf[2] = 2; /* method username/password */
+    plink->mode |= TCP_LINK_SOCKS_AUTHORIZATION;
+  }
+#ifdef _WIN32
+  if(send(plink->socket, buf, 3, 0) != 3)
+    return errno;
+#else
+  if(write(plink->socket, buf, 3) != 3)
+    return errno;
+#endif
+  return 0;
+}
+
+int icq_TCPLinkProxyAuthorization(icq_TCPLink *plink)
+{
+  int res;
+  char buf[1024];
+
+  plink->mode = (plink->mode & (~TCP_LINK_SOCKS_AUTHORIZATION)) | TCP_LINK_SOCKS_AUTHSTATUS;
+#ifdef _WIN32
+  res = recv(plink->socket, buf, 2, 0);
+#else
+  res = read(plink->socket, buf, 2);
+#endif
+  if(res != 2 || buf[0] != 5 || buf[1] != 2) /* username/password authentication*/
+  {
+    icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Authentication method incorrect\n");
+#ifdef _WIN32
+    closesocket(plink->socket);
+#else
+    close(plink->socket);
+#endif
+    return -1;
+  }
+  buf[0] = 1; /* version of subnegotiation */
+  buf[1] = strlen(plink->icqlink->icq_ProxyName);
+  memcpy(&buf[2], plink->icqlink->icq_ProxyName, buf[1]);
+  buf[2+buf[1]] = strlen(plink->icqlink->icq_ProxyPass);
+  memcpy(&buf[3+buf[1]], plink->icqlink->icq_ProxyPass, buf[2+buf[1]]);
+#ifdef _WIN32
+  if(send(plink->socket, buf, buf[1]+buf[2+buf[1]]+3, 0) != buf[1] + buf[2+buf[1]]+3)
+    return errno;
+#else
+  if(write(plink->socket, buf, buf[1]+buf[2+buf[1]]+3) != buf[1] + buf[2+buf[1]]+3)
+    return errno;
+#endif
+  return 0;
+}
+
+int icq_TCPLinkProxyAuthStatus(icq_TCPLink *plink)
+{
+  int res;
+  char buf[20];
+
+  plink->mode = (plink->mode & (~TCP_LINK_SOCKS_AUTHSTATUS)) | TCP_LINK_SOCKS_CROSSCONNECT;
+#ifdef _WIN32
+  res = recv(plink->socket, buf, 2, 0);
+#else
+  res = read(plink->socket, buf, 2);
+#endif
+  if(res != 2 || buf[0] != 1 || buf[1] != 0)
+  {
+    icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Authorization failure\n");
+#ifdef _WIN32
+    closesocket(plink->socket);
+#else
+    close(plink->socket);
+#endif
+    return -1;
+  }
+  return 0;
+}
+
+int icq_TCPLinkProxyNoAuthStatus(icq_TCPLink *plink)
+{
+  int res;
+  char buf[20];
+
+  plink->mode = (plink->mode & (~TCP_LINK_SOCKS_NOAUTHSTATUS)) | TCP_LINK_SOCKS_CROSSCONNECT;
+#ifdef _WIN32
+  res = recv(plink->socket, buf, 2, 0);
+#else
+  res = read(plink->socket, buf, 2);
+#endif
+  if(res != 2 || buf[0] != 5 || buf[1] != 0) /* no authentication required */
+  {
+    icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Authentication method incorrect\n");
+#ifdef _WIN32
+    closesocket(plink->socket);
+#else
+    close(plink->socket);
+#endif
+    return -1;
+  }
+  return 0;
+}
+
+int icq_TCPLinkProxyCrossConnect(icq_TCPLink *plink)
+{
+  char buf[20];
+
+  plink->mode = (plink->mode & ~(TCP_LINK_SOCKS_CROSSCONNECT)) | TCP_LINK_SOCKS_CONNSTATUS;
+  buf[0] = 5; /* protocol version */
+  buf[1] = 1; /* command connect */
+  buf[2] = 0; /* reserved */
+  buf[3] = 1; /* address type IP v4 */
+  memcpy(&buf[4], &plink->remote_address.sin_addr.s_addr, 4);
+  memcpy(&buf[8], &plink->remote_address.sin_port, 2);
+#ifdef _WIN32
+  if(send(plink->socket, buf, 10, 0) != 10)
+    return errno;
+#else
+  if(write(plink->socket, buf, 10) != 10)
+    return errno;
+#endif
+  return 0;
+}
+
+int icq_TCPLinkProxyConnectStatus(icq_TCPLink *plink)
+{
+  int res;
+  char buf[1024];
+
+  plink->mode = (plink->mode & (~TCP_LINK_SOCKS_CONNSTATUS));
+#ifdef _WIN32
+  res = recv(plink->socket, buf, 10, 0);
+#else
+  res = read(plink->socket, buf, 10);
+#endif
+  if(res != 10 || buf[0] != 5 || buf[1] != 0)
+  {
+    switch(buf[1])
+    {
+      case 1:
+        icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] General SOCKS server failure\n");
+        res = EFAULT;
+        break;
+      case 2:
+        icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Connection not allowed by ruleset\n");
+        res = EACCES;
+        break;
+      case 3:
+        icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Network unreachable\n");
+        res = ENETUNREACH;
+        break;
+      case 4:
+        icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Host unreachable\n");
+        res = ENETUNREACH;
+        break;
+      case 5:
+        icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Connection refused\n");
+        res = ECONNREFUSED;
+        break;
+      case 6:
+        icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] TTL expired\n");
+        res = ETIMEDOUT;
+        break;
+      case 7:
+        icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Command not supported\n");
+        res = EOPNOTSUPP;
+        break;
+      case 8:
+        icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Address type not supported\n");
+        res = EAFNOSUPPORT;
+        break;
+      default:
+        icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Unknown SOCKS server failure\n");
+        res = EFAULT;
+        break;
+    }
+#ifdef _WIN32
+    closesocket(plink->socket);
+#else
+    close(plink->socket);
+#endif
+    return res;
+  }
+  return 0;
+}
+
+int icq_TCPLinkConnect(icq_TCPLink *plink, DWORD uin, int port)
+{
+  icq_ContactItem *pcontact=icq_ContactFind(plink->icqlink, uin);
+  icq_Packet *p;
+  int result;
+
+#ifndef _WIN32
+  int flags;
+#else
+  u_long iosflag;
+#endif
+
+  /* these return values never and nowhere checked */
+  /*                                   denis.      */
+  if(!pcontact)
+    return -2;
+
+  if((plink->socket=socket(AF_INET, SOCK_STREAM, 0)) < 0)
+    return -3;
+
+/*   bzero(&(plink->remote_address), sizeof(plink->remote_address));   Win32 incompatible... */
+  memset(&(plink->remote_address), 0, sizeof(plink->remote_address));
+  plink->remote_address.sin_family = AF_INET;
+
+  /* if our IP is the same as the remote user's ip, connect to real_ip
+     instead since we're both probably behind a firewall */
+  icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE,
+    "local IP is %08X:%d, remote real IP is %08X:%d, remote IP is %08X:%d, port is %d\n",
+    plink->icqlink->icq_OurIP,
+    plink->icqlink->icq_OurPort,
+    pcontact->remote_real_ip,
+    pcontact->remote_port,
+    pcontact->remote_ip,
+    pcontact->remote_port,
+    port
+    );
+  if (plink->icqlink->icq_OurIP == pcontact->remote_ip) 
+    plink->remote_address.sin_addr.s_addr = htonl(pcontact->remote_real_ip);
+  else 
+    plink->remote_address.sin_addr.s_addr = htonl(pcontact->remote_ip);
+
+  if(plink->type==TCP_LINK_MESSAGE)
+  {
+    plink->remote_address.sin_port = htons(pcontact->remote_port);
+    icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, 
+      "initiating message connect to %d (%s:%d)\n", uin, 
+      inet_ntoa(*((struct in_addr *)(&(plink->remote_address.sin_addr)))),
+      pcontact->remote_port);
+  }
+  else
+  {
+  plink->remote_address.sin_port = htons(port);
+    icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, 
+      "initiating file/chat connect to %d (%s:%d)\n", uin, 
+      inet_ntoa(*((struct in_addr *)(&(plink->remote_address.sin_addr)))),
+      port);
+  }
+
+  /* set the socket to non-blocking */
+#ifdef _WIN32
+  iosflag = TRUE;
+  ioctlsocket(plink->socket, FIONBIO, &iosflag);
+#else
+  flags=fcntl(plink->socket, F_GETFL, 0);
+  fcntl(plink->socket, F_SETFL, flags | O_NONBLOCK);
+#endif
+
+  if(!plink->icqlink->icq_UseProxy)
+    result=connect(plink->socket, (struct sockaddr *)&(plink->remote_address),
+       sizeof(plink->remote_address));
+  else /* SOCKS proxy support */
+    result=icq_TCPLinkProxyConnect(plink, uin, port);
+  /* FIXME: Here we should check for errors on connection */
+  /* because of proxy support - it can't be checked       */
+  /* by getsockopt() later in _handle_ready_sockets()     */
+  /*                                  denis.              */
+
+  plink->mode|=TCP_LINK_MODE_CONNECTING;
+
+  plink->remote_uin=uin;
+
+  plink->connect_time=time(0L);
+
+  /* Send the hello packet */
+  p=icq_TCPCreateInitPacket(plink);
+  icq_TCPLinkSend(plink, p);
+
+#ifdef TCP_PACKET_TRACE
+  printf("hello packet queued for %lu\n", uin);
+#endif /* TCP_PACKET_TRACE */
+
+  return 1;
+}
+
+icq_TCPLink *icq_TCPLinkAccept(icq_TCPLink *plink)
+{
+#ifdef _WIN32
+  u_long iosflag;
+#else
+  int flags;
+#endif
+  int socket;
+  size_t remote_length;
+  icq_TCPLink *pnewlink=icq_TCPLinkNew( plink->icqlink );
+  
+  if(pnewlink)
+  {
+		socket=accept(plink->socket, (struct sockaddr *)&(plink->remote_address),
+                  &remote_length);
+
+		icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE,
+			"accepting tcp connection from %s:%d\n",
+			inet_ntoa(*((struct in_addr *)(&(plink->remote_address.sin_addr)))),
+			ntohs(plink->remote_address.sin_port));
+
+		/* FIXME: make sure accept succeeded */
+
+    pnewlink->type=plink->type;
+    pnewlink->socket=socket;
+
+    /* first packet sent on an icq tcp link is always the hello packet */
+    pnewlink->mode|=TCP_LINK_MODE_HELLOWAIT;
+  }
+
+  /* set the socket to non-blocking */
+#ifdef _WIN32
+  iosflag = TRUE;
+  ioctlsocket(plink->socket, FIONBIO, &iosflag);
+#else
+  flags=fcntl(pnewlink->socket, F_GETFL, 0);
+  fcntl(pnewlink->socket, F_SETFL, flags | O_NONBLOCK);
+#endif
+  
+  return pnewlink;
+}
+
+int icq_TCPLinkListen(icq_TCPLink *plink)
+{
+  unsigned int t;
+
+  /* listening links have 0 uin */
+  plink->remote_uin=0;
+
+  /* create tcp listen socket */
+  if((plink->socket=socket(AF_INET, SOCK_STREAM, 0)) < 0)
+    return -1;
+
+  /* must use memset, no bzero for Win32! */
+  memset(&plink->socket_address, 0, sizeof(struct sockaddr_in));
+  plink->socket_address.sin_family=AF_INET;
+  plink->socket_address.sin_addr.s_addr=htonl(INADDR_ANY);
+  plink->socket_address.sin_port=0;
+
+  if(bind(plink->socket, (struct sockaddr *)&plink->socket_address, sizeof(struct sockaddr_in)) < 0)
+    return -2;
+
+  if(listen(plink->socket, 5) < 0)
+    return -3;
+
+  t=sizeof(struct sockaddr_in);
+  if(getsockname(plink->socket, (struct sockaddr *)&plink->socket_address, &t) < 0)
+    return -4;
+
+  icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE,
+             "created tcp listening socket %d, local address=%s:%d\n",
+             plink->socket,
+             inet_ntoa(*((struct in_addr *)(&plink->socket_address.sin_addr))),
+             ntohs(plink->socket_address.sin_port));
+
+  plink->mode|=TCP_LINK_MODE_LISTEN;
+  
+  return 0;
+}
+
+/* Doing Cyrillic translations for Chat dialog sessions */
+void icq_ChatRusConv_n(const char to[4], char *t_in, int t_len)
+{
+  int i, j;
+  
+  for(i = j = 0; i < t_len; ++i)
+  {
+    if((((unsigned char)t_in[i]) < ' ') && (t_in[i] != '\r'))
+    {
+      if(i - 1 > j)
+        icq_RusConv_n(to, &t_in[j], i - j - 1);
+      switch(t_in[i])
+      {
+        case '\x07': /* Bell */
+        case '\x08': /* BackSpace */
+        case '\x03': /* Chat is active */
+        case '\x04': /* Chat is not active */
+             break;
+        case '\x00': /* Foregroung color (RR GG BB ?? ) */
+        case '\x01': /* Background color (RR GG BB ?? ) */
+        case '\x11': /* Font style change (Bold - 1, Italic - 2, Underline - 4) */
+        case '\x12': /* Font size change */
+             i += 4;
+             break;
+        case '\x10': /* Font family and encoding change */
+             i += t_in[i+1] + 2 + 2;
+             icq_RusConv_n(to, &t_in[i+3], t_in[i+1]);
+             break;
+      }
+      j = i + 1;
+    }
+  }
+  if(i > t_len)
+    i = t_len;
+  if(j > t_len)
+    j = t_len;
+  if(i > j)
+    icq_RusConv_n(to, &t_in[j], i - j);
+}
+
+int icq_TCPLinkOnDataReceived(icq_TCPLink *plink)
+{
+  int process_count=0, recv_result=0;
+  char *buffer=plink->buffer;
+
+  do { /* while recv_result > 0 */
+
+    int done=0;
+
+    /* append received data onto end of buffer */
+    if((recv_result=recv(plink->socket, buffer+plink->buffer_count,
+      icq_TCPLinkBufferSize-plink->buffer_count, 0)) < 1)
+    {
+      /* either there was an error or the remote side has closed 
+       * the connection - fall out of the loop */
+      continue;
+    };
+  
+    plink->buffer_count+=recv_result;
+
+#ifdef TCP_BUFFER_TRACE
+    printf("received %d bytes from link %x, new buffer count %d\n",
+      recv_result, plink, plink->buffer_count);
+
+    hex_dump(plink->buffer, plink->buffer_count);
+#endif /*TCP_BUFFER_TRACE*/
+
+    process_count+=recv_result;
+
+    /* don't do any packet processing if we're in raw mode */
+    if(plink->mode & TCP_LINK_MODE_RAW) {
+      /* notify the app with the new data */
+      if(plink->type == TCP_LINK_CHAT)
+        icq_ChatRusConv_n("wk", plink->buffer, plink->buffer_count);
+      if(plink->icqlink->icq_RequestNotify)
+        (*plink->icqlink->icq_RequestNotify)(plink->icqlink, plink->id, ICQ_NOTIFY_CHATDATA,
+                           plink->buffer_count, plink->buffer);
+      plink->buffer_count=0;
+      continue;
+    }
+
+    /* remove packets from the buffer until the buffer is empty
+     * or the remaining bytes do not equal a full packet */
+    while((unsigned)plink->buffer_count>sizeof(WORD) && !done)
+    {
+      WORD packet_size=(*((WORD *)buffer));
+
+      /* warn if the buffer is too small to hold the whole packet */
+      if(packet_size>icq_TCPLinkBufferSize-sizeof(WORD))
+      {
+        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;
+      }
+
+      if(packet_size+sizeof(WORD) <= (unsigned)plink->buffer_count)
+      {
+        /* copy the packet into memory */
+        icq_Packet *p=icq_PacketNew();
+        icq_PacketAppend(p, buffer+sizeof(WORD), packet_size);
+
+        /* remove it from the buffer */
+        memcpy(buffer, buffer+packet_size+sizeof(WORD),
+             plink->buffer_count-packet_size-sizeof(WORD));
+
+        plink->buffer_count-=(packet_size+sizeof(WORD));
+
+        icq_TCPLinkOnPacketReceived(plink, p);
+      }
+      else
+      {
+        /* not enough bytes in buffer to form the complete packet.
+         * we're done for now */
+        done=1;
+      }
+    } /* while packets remain in buffer */
+
+  } while (recv_result > 0);
+
+  if (recv_result < 0 && errno!=EWOULDBLOCK) {
+
+    /* receive error - log it */
+    icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "recv failed from %d (%d-%s),"
+      " closing link\n", plink->remote_uin, errno, strerror(errno));
+
+  }
+
+  return process_count;
+}
+
+void icq_TCPLinkOnPacketReceived(icq_TCPLink *plink, icq_Packet *p)
+{
+
+#ifdef TCP_RAW_TRACE
+  printf("packet received! { length=%d }\n", p->length);
+  icq_PacketDump(p);
+#endif
+
+  /* Stick packet on ready packet linked list */
+  list_enqueue(plink->received_queue, p);
+}
+
+void icq_TCPLinkOnConnect(icq_TCPLink *plink)
+{
+#ifdef _WIN32
+  int len;
+#else
+  size_t len;
+#endif
+  int error;
+  
+  /* check getsockopt */
+  len=sizeof(error);
+
+#ifdef _WIN32
+  getsockopt(plink->socket, SOL_SOCKET, SO_ERROR, (char *)&error, &len);
+#else
+  getsockopt(plink->socket, SOL_SOCKET, SO_ERROR, &error, &len);
+#endif
+  if(!error && (plink->mode & (TCP_LINK_SOCKS_CONNECTING | TCP_LINK_SOCKS_AUTHORIZATION |
+                               TCP_LINK_SOCKS_AUTHSTATUS | TCP_LINK_SOCKS_NOAUTHSTATUS |
+                               TCP_LINK_SOCKS_CROSSCONNECT | TCP_LINK_SOCKS_CONNSTATUS)))
+  {
+    if(plink->mode & TCP_LINK_SOCKS_CONNECTING)
+       error = icq_TCPLinkProxyRequestAuthorization(plink);
+    else if(plink->mode & TCP_LINK_SOCKS_AUTHORIZATION)
+      error = icq_TCPLinkProxyAuthorization(plink);
+    else if(plink->mode & TCP_LINK_SOCKS_AUTHSTATUS)
+      error = icq_TCPLinkProxyAuthStatus(plink);
+    else if(plink->mode & TCP_LINK_SOCKS_NOAUTHSTATUS)
+      error = icq_TCPLinkProxyNoAuthStatus(plink);
+    else if(plink->mode & TCP_LINK_SOCKS_CROSSCONNECT)
+      error = icq_TCPLinkProxyCrossConnect(plink);
+    else if(plink->mode & TCP_LINK_SOCKS_CONNSTATUS)
+      error = icq_TCPLinkProxyConnectStatus(plink);
+    else
+      error = EINVAL;
+  }
+
+  if(error)
+  {
+    /* connection failed- close the link, which takes care
+     * of notifying the app about packets that didn't make it */
+    icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "connect failed to %d (%d-%s),"
+       " closing link\n", plink->remote_uin, error, strerror(error));
+
+    icq_TCPLinkClose(plink);
+    return;
+  }
+
+  if(plink->mode & (TCP_LINK_SOCKS_CONNECTING | TCP_LINK_SOCKS_AUTHORIZATION | TCP_LINK_SOCKS_AUTHSTATUS | TCP_LINK_SOCKS_NOAUTHSTATUS | TCP_LINK_SOCKS_CROSSCONNECT | TCP_LINK_SOCKS_CONNSTATUS))
+    return;
+
+  len=sizeof(plink->socket_address);
+  getsockname(plink->socket, (struct sockaddr *)&plink->socket_address, &len);
+
+  icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE,
+             "connected to uin %d, socket=%d local address=%s:%d remote address=%s:%d\n",
+             plink->remote_uin, plink->socket,
+             inet_ntoa(*((struct in_addr *)(&plink->socket_address.sin_addr))),
+             ntohs(plink->socket_address.sin_port),
+             inet_ntoa(*((struct in_addr *)(&plink->remote_address.sin_addr))),
+             ntohs(plink->remote_address.sin_port));
+
+  plink->mode&= ~TCP_LINK_MODE_CONNECTING;
+
+  /* socket is now connected, notify each request that connection
+   * has been established and send pending data */
+  while(plink->send_queue->count>0)
+  {
+    icq_Packet *p=list_dequeue(plink->send_queue);
+    if(p->id)
+      if(plink->icqlink->icq_RequestNotify)
+        (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_CONNECTED, 0, 0);
+    icq_TCPLinkSend(plink, p);
+  }
+
+  /* yeah this probably shouldn't be here.  oh well :) */
+  if(plink->type==TCP_LINK_CHAT)
+  {
+    icq_ChatSessionSetStatus((icq_ChatSession *)plink->session,
+      CHAT_STATUS_CONNECTED);
+    icq_ChatSessionSetStatus((icq_ChatSession *)plink->session, 
+      CHAT_STATUS_WAIT_ALLINFO);
+  }
+
+  if(plink->type==TCP_LINK_FILE)
+  {
+    icq_FileSessionSetStatus((icq_FileSession *)plink->session,
+      FILE_STATUS_CONNECTED);
+  }
+
+}
+
+unsigned long icq_TCPLinkSendSeq(icq_TCPLink *plink, icq_Packet *p,
+  unsigned long sequence)
+{
+  /* append the next sequence number on the packet */
+  if (!sequence)
+    sequence=plink->icqlink->icq_TCPSequence--;
+  p->id=sequence;
+  icq_PacketEnd(p);
+  icq_PacketAppend32(p, sequence);
+
+  /* if the link is currently connecting, queue the packets for
+   * later, else send immediately */
+  if(plink->mode & TCP_LINK_MODE_CONNECTING) {
+    list_insert(plink->send_queue, 0, p);
+    if(plink->icqlink->icq_RequestNotify)
+      (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_CONNECTING, 0, 0);
+  } else {
+    icq_PacketSend(p, plink->socket);
+    if(p->id)
+      if(plink->icqlink->icq_RequestNotify)
+        (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_SENT, 0, 0);
+    icq_PacketDelete(p);
+  }
+  return sequence;
+}
+
+void icq_TCPLinkSend(icq_TCPLink *plink, icq_Packet *p)
+{
+  /* if the link is currently connecting, queue the packets for
+   * later, else send immediately */
+  if(plink->mode & TCP_LINK_MODE_CONNECTING) {
+    list_insert(plink->send_queue, 0, p);
+    if(plink->icqlink->icq_RequestNotify)
+      (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_CONNECTING, 0, 0);
+  } else {
+    icq_PacketSend(p, plink->socket);
+    if(p->id)
+      if(plink->icqlink->icq_RequestNotify)
+        (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_SENT, 0, 0);
+    icq_PacketDelete(p);
+  }
+}
+
+void icq_TCPLinkProcessReceived(icq_TCPLink *plink)
+{
+  list *plist=plink->received_queue;
+  while(plist->count>0)
+
+  {
+    icq_Packet *p=list_dequeue(plist);
+
+    if(plink->mode & TCP_LINK_MODE_HELLOWAIT)
+    {
+      icq_TCPProcessHello(p, plink);
+    }
+    else
+    {
+
+      switch (plink->type) {
+
+        case TCP_LINK_MESSAGE:
+          icq_TCPProcessPacket(p, plink);
+          break;
+
+        case TCP_LINK_CHAT:
+          icq_TCPProcessChatPacket(p, plink);
+          break;
+
+        case TCP_LINK_FILE:
+          icq_TCPProcessFilePacket(p, plink);
+          break;
+
+      }
+    }
+
+    icq_PacketDelete(p);
+  }
+
+}
+
+int _icq_FindTCPLink(void *p, va_list data)
+{
+  icq_TCPLink *plink=(icq_TCPLink *)p;
+  unsigned long uin=va_arg(data, unsigned long);
+  int type=va_arg(data, int);
+
+  return ( (plink->remote_uin == uin ) && (plink->type == type) );
+}
+
+icq_TCPLink *icq_FindTCPLink(ICQLINK *link, unsigned long uin, int type)
+{
+  return list_traverse(link->icq_TCPLinks, _icq_FindTCPLink, uin, type);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/tcplink.h	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,97 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+#ifndef _TCP_LINK_H_
+#define _TCP_LINK_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef _WIN32
+#include <winsock.h>
+#else
+#include <netinet/in.h>
+#endif
+
+#include <time.h>
+
+#include "icq.h"
+#include "icqpacket.h"
+#include "list.h"
+
+/* link mode bitfield values */
+#define TCP_LINK_MODE_RAW             1
+#define TCP_LINK_MODE_HELLOWAIT       2
+#define TCP_LINK_MODE_LISTEN          4
+#define TCP_LINK_MODE_CONNECTING      8
+#define TCP_LINK_SOCKS_CONNECTING     16
+#define TCP_LINK_SOCKS_AUTHORIZATION  32
+#define TCP_LINK_SOCKS_AUTHSTATUS     64
+#define TCP_LINK_SOCKS_NOAUTHSTATUS   128
+#define TCP_LINK_SOCKS_CROSSCONNECT   256
+#define TCP_LINK_SOCKS_CONNSTATUS     512
+
+/* link types */
+#define TCP_LINK_MESSAGE              1
+#define TCP_LINK_CHAT                 2
+#define TCP_LINK_FILE                 3
+
+#define icq_TCPLinkBufferSize 4096
+#define TCP_LINK_CONNECT_TIMEOUT 30
+
+typedef struct icq_TCPLink_s
+{
+   /* icq_TCPLink ICQLINK, type, mode, and session */
+   ICQLINK *icqlink;
+   int type;
+   int mode;
+   int proxy_status;
+   void *session;
+	 
+   /* socket parameters */
+   int socket;
+   struct sockaddr_in socket_address;
+   struct sockaddr_in remote_address;
+
+   /* data buffer for receive calls */
+   char buffer[icq_TCPLinkBufferSize];
+   int buffer_count;
+
+   /* packet queues */
+   list *received_queue;
+   list *send_queue;
+
+   /* icq specific data, initialized by hello packet */
+   unsigned long id;
+   unsigned long remote_version;
+   unsigned long remote_uin;
+   char flags;
+
+   /* connect timer */
+   time_t connect_time;
+
+} icq_TCPLink;
+
+icq_TCPLink *icq_TCPLinkNew(ICQLINK *link);
+void icq_TCPLinkDelete(void *p);
+void icq_TCPLinkClose(icq_TCPLink *p);
+void icq_TCPLinkNodeDelete(list_node *p);
+
+int icq_TCPLinkConnect(icq_TCPLink *plink, DWORD uin, int port);
+icq_TCPLink *icq_TCPLinkAccept(icq_TCPLink *plink);
+int icq_TCPLinkListen(icq_TCPLink *plink);
+
+int icq_TCPLinkOnDataReceived(icq_TCPLink *plink);
+void icq_TCPLinkOnPacketReceived(icq_TCPLink *plink, icq_Packet *p);
+void icq_TCPLinkOnConnect(icq_TCPLink *plink);
+
+unsigned long icq_TCPLinkSendSeq(icq_TCPLink *plink, icq_Packet *p,
+  unsigned long sequence);
+void icq_TCPLinkSend(icq_TCPLink *plink, icq_Packet *p);
+
+void icq_TCPLinkProcessReceived(icq_TCPLink *plink);
+
+icq_TCPLink *icq_FindTCPLink(ICQLINK *link, unsigned long uin, int type);
+
+void icq_ChatRusConv_n(const char to[4], char *t_in, int t_len);
+
+#endif /* _TCP_LINK_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/udp.c	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,785 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+$Id: udp.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Log$
+Revision 1.1  2000/11/28 02:22:42  warmenhoven
+icq. whoop de doo
+
+Revision 1.23  2000/07/09 22:19:35  bills
+added new *Close functions, use *Close functions instead of *Delete
+where correct, and misc cleanup
+
+Revision 1.22  2000/07/09 18:25:44  denis
+icq_UpdateNewUserInfo() now returns seq1 instead of seq2 since it
+isn't META function.
+
+Revision 1.21  2000/06/25 16:43:19  denis
+icq_SendMetaInfoReq() was added.
+All icq_*Meta*() functions now returns sequence number 2 because their
+replies from the server are synced with it.
+
+Revision 1.20  2000/06/15 01:50:39  bills
+removed *Seq functions
+
+Revision 1.19  2000/05/10 19:06:59  denis
+UDP outgoing packet queue was implemented.
+
+Revision 1.18  2000/05/03 18:34:43  denis
+icq_UpdateNewUserInfo() was added.
+All icq_UpdateMetaInfo*() now return their sequence number.
+
+Revision 1.17  2000/04/10 16:36:04  denis
+Some more Win32 compatibility from Guillaume Rosanis <grs@mail.com>
+
+Revision 1.16  2000/04/06 19:03:07  denis
+return sequence number
+
+Revision 1.15  2000/04/06 16:36:18  denis
+So called "Online List problem" bug with Long Contact List was fixed.
+icq_*Send*Seq() functions with specified sequence number were added.
+
+Revision 1.14  2000/04/05 14:37:02  denis
+Applied patch from "Guillaume R." <grs@mail.com> for basic Win32
+compatibility.
+
+Revision 1.13  1999/12/27 11:12:35  denis
+icq_UpdateMetaInfoSecurity() added for setting "My authorization is
+required", "Web Aware" and "IP Publishing".
+
+Revision 1.12  1999/10/14 11:43:28  denis
+icq_UpdateMetaInfo* functions added.
+
+Revision 1.11  1999/10/07 18:36:27  denis
+proxy.h file removed.
+
+Revision 1.10  1999/10/04 13:36:17  denis
+Cleanups.
+
+Revision 1.9  1999/09/29 20:15:30  bills
+tcp port wasn't being sent properly in login packet
+
+Revision 1.8  1999/09/29 17:13:45  denis
+Webaware functions enabled without success even with UDP v5 - need more
+investigations.
+
+Revision 1.7  1999/07/18 20:22:16  bills
+changed to use new byte-order functions & contact list functions
+
+Revision 1.6  1999/07/16 15:46:00  denis
+Cleaned up.
+
+Revision 1.5  1999/07/16 12:40:53  denis
+ICQ UDP v5 implemented.
+Encription for ICQ UDP v5 implemented.
+icq_Packet* unified interface for UDP packets implemented.
+Multipacket support of ICQ UDP v5 support added.
+
+Revision 1.4  1999/07/12 15:13:43  cproch
+- added definition of ICQLINK to hold session-specific global variabled
+  applications which have more than one connection are now possible
+- changed nearly every function defintion to support ICQLINK parameter
+
+Revision 1.3  1999/04/29 09:40:52  denis
+Unsuccessful attempt to implement web presence (webaware) feature
+
+Revision 1.2  1999/04/14 15:04:13  denis
+Cleanups for "strict" compiling (-ansi -pedantic)
+Switched from icq_Log callback to icq_Fmt function.
+
+Revision 1.1  1999/03/24 11:37:38  denis
+Underscored files with TCP stuff renamed.
+TCP stuff cleaned up
+Function names changed to corresponding names.
+icqlib.c splitted to many small files by subject.
+C++ comments changed to ANSI C comments.
+
+*/
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#ifdef _WIN32
+#include <winsock.h>
+#endif
+
+#include <stdlib.h>
+
+#include "icqtypes.h"
+#include "icqlib.h"
+#include "udp.h"
+#include "queue.h"
+
+#include "stdpackets.h"
+#include "icqbyteorder.h"
+
+static const BYTE icq_UDPTable[] = {
+  0x59, 0x60, 0x37, 0x6B, 0x65, 0x62, 0x46, 0x48, 0x53, 0x61, 0x4C, 0x59, 0x60, 0x57, 0x5B, 0x3D,
+  0x5E, 0x34, 0x6D, 0x36, 0x50, 0x3F, 0x6F, 0x67, 0x53, 0x61, 0x4C, 0x59, 0x40, 0x47, 0x63, 0x39,
+  0x50, 0x5F, 0x5F, 0x3F, 0x6F, 0x47, 0x43, 0x69, 0x48, 0x33, 0x31, 0x64, 0x35, 0x5A, 0x4A, 0x42,
+  0x56, 0x40, 0x67, 0x53, 0x41, 0x07, 0x6C, 0x49, 0x58, 0x3B, 0x4D, 0x46, 0x68, 0x43, 0x69, 0x48,
+  0x33, 0x31, 0x44, 0x65, 0x62, 0x46, 0x48, 0x53, 0x41, 0x07, 0x6C, 0x69, 0x48, 0x33, 0x51, 0x54,
+  0x5D, 0x4E, 0x6C, 0x49, 0x38, 0x4B, 0x55, 0x4A, 0x62, 0x46, 0x48, 0x33, 0x51, 0x34, 0x6D, 0x36,
+  0x50, 0x5F, 0x5F, 0x5F, 0x3F, 0x6F, 0x47, 0x63, 0x59, 0x40, 0x67, 0x33, 0x31, 0x64, 0x35, 0x5A,
+  0x6A, 0x52, 0x6E, 0x3C, 0x51, 0x34, 0x6D, 0x36, 0x50, 0x5F, 0x5F, 0x3F, 0x4F, 0x37, 0x4B, 0x35,
+  0x5A, 0x4A, 0x62, 0x66, 0x58, 0x3B, 0x4D, 0x66, 0x58, 0x5B, 0x5D, 0x4E, 0x6C, 0x49, 0x58, 0x3B,
+  0x4D, 0x66, 0x58, 0x3B, 0x4D, 0x46, 0x48, 0x53, 0x61, 0x4C, 0x59, 0x40, 0x67, 0x33, 0x31, 0x64,
+  0x55, 0x6A, 0x32, 0x3E, 0x44, 0x45, 0x52, 0x6E, 0x3C, 0x31, 0x64, 0x55, 0x6A, 0x52, 0x4E, 0x6C,
+  0x69, 0x48, 0x53, 0x61, 0x4C, 0x39, 0x30, 0x6F, 0x47, 0x63, 0x59, 0x60, 0x57, 0x5B, 0x3D, 0x3E,
+  0x64, 0x35, 0x3A, 0x3A, 0x5A, 0x6A, 0x52, 0x4E, 0x6C, 0x69, 0x48, 0x53, 0x61, 0x6C, 0x49, 0x58,
+  0x3B, 0x4D, 0x46, 0x68, 0x63, 0x39, 0x50, 0x5F, 0x5F, 0x3F, 0x6F, 0x67, 0x53, 0x41, 0x25, 0x41,
+  0x3C, 0x51, 0x54, 0x3D, 0x5E, 0x54, 0x5D, 0x4E, 0x4C, 0x39, 0x50, 0x5F, 0x5F, 0x5F, 0x3F, 0x6F,
+  0x47, 0x43, 0x69, 0x48, 0x33, 0x51, 0x54, 0x5D, 0x6E, 0x3C, 0x31, 0x64, 0x35, 0x5A, 0x00, 0x00,
+};
+
+void icq_UDPCheckCode(icq_Packet *p)
+{
+  DWORD num1, num2;
+  DWORD r1,r2;
+
+  num1 = p->data[8];
+  num1 <<= 8;
+  num1 += p->data[4];
+  num1 <<= 8;
+  num1 += p->data[2];
+  num1 <<= 8;
+  num1 += p->data[6];
+
+  r1 = 0x18 + (rand() % (p->length - 0x18));
+  r2 = rand() & 0xff;
+
+  num2 = r1;
+  num2 <<= 8;
+  num2 += p->data[r1];
+  num2 <<= 8;
+  num2 += r2;   
+  num2 <<= 8;
+  num2 += icq_UDPTable[r2];
+  num2 ^= 0xFF00FF;
+
+  icq_PacketGoto(p, 0x14);
+  icq_PacketAppend32(p, num1 ^ num2);
+}
+
+DWORD icq_UDPScramble(DWORD cc)
+{
+  DWORD a[5];
+
+  a[0] = cc & 0x0000001F;
+  a[1] = cc & 0x03E003E0;
+  a[2] = cc & 0xF8000400;
+  a[3] = cc & 0x0000F800;
+  a[4] = cc & 0x041F0000;
+
+  a[0] <<= 0x0C;
+  a[1] <<= 0x01;
+  a[2] >>= 0x0A;
+  a[3] <<= 0x10;
+  a[4] >>= 0x0F;
+
+  return a[0] + a[1] + a[2] + a[3] + a[4];
+}
+
+void icq_UDPEncode(icq_Packet *p)
+{
+  DWORD checkcode;
+  DWORD code1, code2, code3;
+  DWORD pos;
+  DWORD data;
+
+  icq_UDPCheckCode(p);
+  icq_PacketGoto(p, 20);
+  checkcode = icq_PacketRead32(p);
+  code1 = p->length * 0x68656c6cL;
+  code2 = code1 + checkcode;
+  pos = 0x0A;
+
+  for(; pos < p->length; pos+=4)
+  {
+    code3 = code2 + icq_UDPTable[pos & 0xFF];
+    data = icqtohl(*(DWORD *)((p->data)+pos));
+    data ^= code3;
+    *(DWORD*)((p->data)+pos)=htoicql(data);
+  }
+  checkcode = icq_UDPScramble(checkcode);
+  *(DWORD *)((p->data)+0x14)=htoicql(checkcode);
+}
+
+/*********************************************************
+icq_UDPSockWrite and icq_UDPSockRead are for _UDP_ packets
+proxy support for TCP sockets is different!
+*********************************************************/
+int icq_UDPSockWriteDirect(ICQLINK *link, icq_Packet *p)
+{
+  char tmpbuf[ICQ_PACKET_DATA_SIZE];
+
+  if(link->icq_UDPSok <= 3)
+  {
+    icq_FmtLog(link, ICQ_LOG_ERROR, "Bad socket!\n");
+    return -1;
+  }
+
+  icq_UDPEncode(p);
+  if(!link->icq_UseProxy)
+  {
+#ifdef _WIN32
+    return send(link->icq_UDPSok, p->data, p->length, 0);
+#else
+    return write(link->icq_UDPSok, p->data, p->length);
+#endif
+  }
+  else
+  {
+    tmpbuf[0] = 0; /* reserved */
+    tmpbuf[1] = 0; /* reserved */
+    tmpbuf[2] = 0; /* standalone packet */
+    tmpbuf[3] = 1; /* address type IP v4 */
+    *(unsigned long*)&tmpbuf[4] = htonl(link->icq_ProxyDestIP);
+    *(unsigned short*)&tmpbuf[8] = htons(link->icq_ProxyDestPort);
+    memcpy(&tmpbuf[10], p->data, p->length);
+#ifdef _WIN32
+    return send(link->icq_UDPSok, tmpbuf, p->length+10, 0)-10;
+#else
+    return write(link->icq_UDPSok, tmpbuf, p->length+10)-10;
+#endif
+  }
+}
+
+int icq_UDPSockWrite(ICQLINK *link, icq_Packet *p)
+{
+  icq_Packet *qp;
+  WORD cmd = icq_PacketReadUDPOutCmd(p);
+  if(cmd != UDP_CMD_ACK && cmd != UDP_CMD_SEND_TEXT_CODE)
+  {
+    qp = (icq_Packet*)malloc(sizeof(icq_Packet));
+    memcpy(qp, p, sizeof(icq_Packet));
+    icq_UDPQueuePut(link, qp, 1);
+    if(link->icq_SetTimeout)
+      link->icq_SetTimeout(link, icq_UDPQueueInterval(link));
+  }
+  return icq_UDPSockWriteDirect(link, p);
+}
+
+int icq_UDPSockRead(ICQLINK *link, icq_Packet *p)
+{
+  int res;
+  char tmpbuf[ICQ_PACKET_DATA_SIZE];
+
+  if(!link->icq_UseProxy)
+  {
+#ifdef _WIN32
+    res = recv(link->icq_UDPSok, p->data, ICQ_PACKET_DATA_SIZE, 0);
+#else
+    res = read(link->icq_UDPSok, p->data, ICQ_PACKET_DATA_SIZE);
+#endif
+    p->length = res;
+    return res;
+  }
+  else
+  {
+#ifdef _WIN32
+    res = recv(link->icq_UDPSok, tmpbuf, ICQ_PACKET_DATA_SIZE, 0);
+#else
+    res = read(link->icq_UDPSok, tmpbuf, ICQ_PACKET_DATA_SIZE);
+#endif
+    if(res<0)
+      return res;
+    memcpy(p->data, &tmpbuf[10], res-10);
+    p->length = res-10;
+    return res-10;
+  }
+}
+
+void icq_HandleTimeout(ICQLINK *link)
+{
+  icq_UDPQueueItem *ptr = 0;
+  icq_Packet *sp = 0, *pack = 0;
+  int attempt;
+  while(icq_UDPQueueInterval(link) == 0)
+  {
+    ptr = (icq_UDPQueueItem*)list_first(link->icq_UDPQueue);
+    attempt = ptr->attempts + 1;
+    if(attempt > 6)
+    {
+      icq_Disconnect(link);
+      if(link->icq_Disconnected)
+        link->icq_Disconnected(link);
+      return;
+    }
+    pack = icq_UDPQueueGet(link);
+    sp = (icq_Packet*)malloc(sizeof(icq_Packet));
+    memcpy(sp, pack, sizeof(icq_Packet));
+    icq_UDPQueuePut(link, pack, attempt);
+    if(link->icq_SetTimeout)
+      link->icq_SetTimeout(link, icq_UDPQueueInterval(link));
+    icq_UDPSockWriteDirect(link, sp);
+    icq_PacketDelete(sp);
+  }
+}
+
+/****************************************
+This must be called every 2 min.
+so the server knows we're still alive.
+JAVA client sends two different commands
+so we do also :)
+*****************************************/
+WORD icq_KeepAlive(ICQLINK *link) /* V5 */
+{
+  icq_Packet *p = icq_UDPCreateStdSeqPacket(link, UDP_CMD_KEEP_ALIVE, link->icq_UDPSeqNum1++);
+  icq_PacketAppend32(p, rand());
+  icq_UDPSockWrite(link, p);
+  icq_PacketDelete(p);
+
+/*  icq_Packet *p = icq_UDPCreateStdPacket(UDP_CMD_KEEP_ALIVE);
+  icq_UDPSockWrite(icq_UDPSok, p);
+  icq_PacketDelete(p);*/
+/*  p = icq_UDPCreateStdPacket(UDP_CMD_KEEP_ALIVE2);
+  icq_UDPSockWrite(icq_Sok, p);
+  icq_PacketDelete(p);*/
+
+  icq_FmtLog(link, ICQ_LOG_MESSAGE, "Send Keep Alive packet to the server\n");
+
+  return link->icq_UDPSeqNum1-1;
+}
+
+/**********************************
+This must be called to remove
+messages from the server
+***********************************/
+void icq_SendGotMessages(ICQLINK *link) /* V5 */
+{
+  icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_ACK_MESSAGES);
+  icq_PacketAppend32(p, rand());
+  icq_UDPSockWrite(link, p);
+  icq_PacketDelete(p);
+}
+
+/*************************************
+this sends over the contact list
+*************************************/
+void icq_SendContactList(ICQLINK *link) /* V5 */
+{
+  char num_used;
+  icq_ContactItem *ptr = icq_ContactGetFirst(link);
+
+  while(ptr)
+  {
+    icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_CONT_LIST);
+
+    num_used = 0;
+    icq_PacketAdvance(p,1);
+    while(ptr && num_used<64)
+    {
+      icq_PacketAppend32(p, ptr->uin);
+      num_used++;
+      ptr = icq_ContactGetNext(ptr);
+    }
+    icq_PacketGotoUDPOutData(p, 0);
+    icq_PacketAppend8(p, num_used);
+    icq_UDPSockWrite(link, p);
+    icq_PacketDelete(p);
+  }
+}
+
+void icq_SendNewUser(ICQLINK *link, unsigned long uin) /* V5 */
+{
+  icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_ADD_TO_LIST);
+  icq_PacketAppend32(p, uin);
+  icq_UDPSockWrite(link, p);
+  icq_PacketDelete(p);
+}
+
+/*************************************
+this sends over the visible list
+that allows certain users to see you
+if you're invisible.
+*************************************/
+void icq_SendVisibleList(ICQLINK *link) /* V5 */
+{
+  char num_used;
+  icq_ContactItem *ptr = icq_ContactGetFirst(link);
+  icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_VIS_LIST);
+
+  num_used = 0;
+  icq_PacketAdvance(p,1);
+  while(ptr)
+  {
+    if(ptr->vis_list)
+    {
+      icq_PacketAppend32(p, ptr->uin);
+      num_used++;
+    }
+    ptr = icq_ContactGetNext(ptr);
+  }
+  if(num_used != 0)
+  {
+    icq_PacketGotoUDPOutData(p, 0);
+    icq_PacketAppend8(p, num_used);
+    icq_UDPSockWrite(link, p);
+  }
+  icq_PacketDelete(p);
+}
+
+void icq_SendInvisibleList(ICQLINK *link) /* V5 */
+{
+  char num_used;
+  icq_ContactItem *ptr = icq_ContactGetFirst(link);
+  icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_INVIS_LIST);
+
+  num_used = 0;
+  icq_PacketAdvance(p,1);
+  while(ptr)
+  {
+    if(ptr->vis_list)
+    {
+      icq_PacketAppend32(p, ptr->uin);
+      num_used++;
+    }
+    ptr = icq_ContactGetNext(ptr);
+  }
+  if(num_used != 0)
+  {
+    icq_PacketGotoUDPOutData(p, 0);
+    icq_PacketAppend8(p, num_used);
+    icq_UDPSockWrite(link, p);
+  }
+  icq_PacketDelete(p);
+}
+
+/**************************************
+This sends the second login command
+this is necessary to finish logging in.
+***************************************/
+void icq_SendLogin1(ICQLINK *link) /* V5 */
+{
+  icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_LOGIN_1);
+  icq_PacketAppend32(p, rand());
+  icq_UDPSockWrite(link, p);
+  icq_PacketDelete(p);
+}
+
+/************************************
+This procedure logins into the server with icq_Uin and pass
+on the socket icq_Sok and gives our ip and port.
+It does NOT wait for any kind of a response.
+*************************************/
+void icq_Login(ICQLINK *link, DWORD status) /* V5 */
+{
+  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;
+
+  p = icq_UDPCreateStdPacket(link, UDP_CMD_LOGIN);
+  icq_PacketAppend32(p, time(0L));
+  icq_PacketAppend32n(p, link->icq_TCPSrvPort);
+  /*icq_PacketAppend16(p, 0);
+  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);
+  else
+    icq_PacketAppend8(p, LOGIN_SNDRCV_TCP);
+  icq_PacketAppend32(p, status);
+  icq_PacketAppend32(p, LOGIN_X3_DEF);
+  icq_PacketAppend32(p, LOGIN_X4_DEF);
+  icq_PacketAppend32(p, LOGIN_X5_DEF);
+
+  icq_UDPSockWrite(link, p);
+  icq_PacketDelete(p);
+}
+
+/**********************
+Logs off ICQ
+***********************/
+void icq_Logout(ICQLINK *link) /* V5 */
+{
+  icq_Packet *p = icq_UDPCreateStdSeqPacket(link, UDP_CMD_SEND_TEXT_CODE, link->icq_UDPSeqNum1++);
+  icq_PacketAppendString(p, "B_USER_DISCONNECTED");
+  icq_PacketAppend8(p, 5);
+  icq_PacketAppend8(p, 0);
+  icq_UDPSockWrite(link, p);
+  icq_PacketDelete(p);
+}
+
+/*******************************
+This routine sends the aknowlegement cmd to the
+server it appears that this must be done after
+everything the server sends us
+*******************************/
+void icq_UDPAck(ICQLINK *link, int seq) /* V5 */
+{
+  icq_Packet *p = icq_UDPCreateStdSeqPacket(link, UDP_CMD_ACK, seq);
+  icq_PacketAppend32(p, rand());
+
+  icq_FmtLog(link, ICQ_LOG_MESSAGE, "Acking\n");
+  icq_UDPSockWrite(link, p);
+  icq_PacketDelete(p);
+}
+
+/***************************************************
+Sends a message thru the server to uin.  Text is the
+message to send.
+***************************************************/
+WORD icq_UDPSendMessage(ICQLINK *link, DWORD uin, const char *text) /* V5 */
+{
+  char buf[512]; /* message may be only 450 bytes long */
+  icq_Packet *p;
+
+  strncpy(buf, text, 512);
+  icq_RusConv("kw", buf);
+
+  p = icq_UDPCreateStdPacket(link, UDP_CMD_SEND_THRU_SRV);
+  icq_PacketAppend32(p, uin);
+  icq_PacketAppend16(p, TYPE_MSG);
+  icq_PacketAppendString(p, buf);
+
+  icq_UDPSockWrite(link, p);
+  icq_PacketDelete(p);
+  return link->icq_UDPSeqNum1-1;
+}
+
+WORD icq_UDPSendURL(ICQLINK *link, DWORD uin, const char *url, const char *descr) /* V5 */
+{
+  char buf1[512], buf2[512];
+  icq_Packet *p;
+
+  strncpy(buf1, descr, 512);
+  icq_RusConv("kw", buf1);
+  strncpy(buf2, url, 512);
+
+  p = icq_UDPCreateStdPacket(link, UDP_CMD_SEND_THRU_SRV);
+  icq_PacketAppend32(p, uin);
+  icq_PacketAppend16(p, TYPE_URL);
+  icq_PacketAppend16(p, strlen(buf1)+strlen(buf2)+2); /* length + the NULL + 0xFE delimiter */
+  icq_PacketAppendStringFE(p, buf1);
+  icq_PacketAppendString0(p, buf2);
+
+  icq_UDPSockWrite(link, p);
+  icq_PacketDelete(p);
+  return link->icq_UDPSeqNum1-1;
+}
+
+/**************************************************
+Sends a authorization to the server so the Mirabilis
+client can add the user.
+***************************************************/
+WORD icq_SendAuthMsg(ICQLINK *link, DWORD uin) /* V5 */
+{
+  icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_SEND_THRU_SRV);
+  icq_PacketAppend32(p, uin);
+  icq_PacketAppend32(p, TYPE_AUTH);
+  icq_PacketAppend16(p, 0);
+  icq_UDPSockWrite(link, p);
+  icq_PacketDelete(p);
+
+  return link->icq_UDPSeqNum1-1;
+}
+
+/**************************************************
+Changes the users status on the server
+***************************************************/
+void icq_ChangeStatus(ICQLINK *link, DWORD status) /* V5 */
+{
+  icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_STATUS_CHANGE);
+  icq_PacketAppend32(p, status);
+  link->icq_Status = status;
+  icq_UDPSockWrite(link, p);
+  icq_PacketDelete(p);
+}
+
+/********************************************************
+Sends a request to the server for info on a specific user
+*********************************************************/
+WORD icq_SendInfoReq(ICQLINK *link, DWORD uin) /* V5 */
+{
+  icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_INFO_REQ);
+  icq_PacketAppend32(p, uin);
+  icq_UDPSockWrite(link, p);
+  icq_PacketDelete(p);
+  return link->icq_UDPSeqNum1-1;
+}
+
+/********************************************************
+Sends a request to the server for info on a specific user
+*********************************************************/
+WORD icq_SendExtInfoReq(ICQLINK *link, DWORD uin) /* V5 */
+{
+  icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_EXT_INFO_REQ);
+  icq_PacketAppend32(p, uin);
+  icq_UDPSockWrite(link, p);
+  icq_PacketDelete(p);
+  return link->icq_UDPSeqNum1-1;
+}
+
+/**************************************************************
+Initializes a server search for the information specified
+***************************************************************/
+void icq_SendSearchReq(ICQLINK *link, const char *email, const char *nick, const char *first,
+                       const char *last) /* V5 */
+{
+  icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_SEARCH_USER);
+  icq_PacketAppendString(p, nick);
+  icq_PacketAppendString(p, first);
+  icq_PacketAppendString(p, last);
+  icq_PacketAppendString(p, email);
+  icq_UDPSockWrite(link, p);
+  icq_PacketDelete(p);
+}
+
+/**************************************************************
+Initializes a server search for the information specified
+***************************************************************/
+void icq_SendSearchUINReq(ICQLINK *link, DWORD uin) /* V5 */
+{
+  icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_SEARCH_UIN);
+  icq_PacketAppend32(p, uin);
+  icq_UDPSockWrite(link, p);
+  icq_PacketDelete(p);
+}
+
+/**************************************************
+Registers a new uin in the ICQ network
+***************************************************/
+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++);
+  strncpy(pass8, pass, 8);
+  icq_PacketAppendString(p, pass8);
+  icq_PacketAppend32(p, 0xA0);
+  icq_PacketAppend32(p, 0x2461);
+  icq_PacketAppend32(p, 0xA00000);
+  icq_PacketAppend32(p, 0x00);
+  icq_PacketGoto(p, 6);
+  icq_PacketAppend32(p, 0);
+  icq_PacketAppend32(p, rand());
+  icq_UDPSockWrite(link, p);
+  icq_FmtLog(link, ICQ_LOG_MESSAGE, "Send RegNewUser packet to the server\n");
+  icq_PacketDelete(p);
+}
+
+WORD icq_UpdateUserInfo(ICQLINK *link, const char *nick, const char *first, const char *last,
+                        const char *email) /* V5 */
+{
+  icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_UPDATE_INFO);
+  icq_PacketAppendString(p, nick);
+  icq_PacketAppendString(p, first);
+  icq_PacketAppendString(p, last);
+  icq_PacketAppendString(p, email);
+/* auth (byte)? */
+  icq_UDPSockWrite(link, p);
+  icq_PacketDelete(p);
+  return link->icq_UDPSeqNum1-1;
+}
+
+WORD icq_UpdateAuthInfo(ICQLINK *link, DWORD auth) /* V5 */
+{
+  icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_UPDATE_AUTH);
+  icq_PacketAppend32(p, auth); /* NOT auth? */
+  icq_UDPSockWrite(link, p);
+  icq_PacketDelete(p);
+  return link->icq_UDPSeqNum1-1;
+}
+
+WORD icq_UpdateMetaInfoSet(ICQLINK *link, const char *nick, const char *first, const char *last,
+                           const char *email, const char *email2, const char *email3,
+                           const char *city, const char *state, const char *phone, const char *fax,
+                           const char *street, const char *cellular, unsigned long zip,
+                           unsigned short cnt_code, unsigned char cnt_stat, unsigned char emailhide)
+{
+  icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_META_USER);
+  icq_PacketAppend16(p, META_CMD_SET_INFO);
+  icq_PacketAppendString(p, nick);
+  icq_PacketAppendString(p, first);
+  icq_PacketAppendString(p, last);
+  icq_PacketAppendString(p, email);
+  icq_PacketAppendString(p, email2);
+  icq_PacketAppendString(p, email3);
+  icq_PacketAppendString(p, city);
+  icq_PacketAppendString(p, state);
+  icq_PacketAppendString(p, phone);
+  icq_PacketAppendString(p, fax);
+  icq_PacketAppendString(p, street);
+  icq_PacketAppendString(p, cellular);
+  icq_PacketAppend32(p, zip);
+  icq_PacketAppend16(p, cnt_code);
+  icq_PacketAppend8(p, cnt_stat);
+  icq_PacketAppend8(p, emailhide);
+  icq_UDPSockWrite(link, p);
+  icq_PacketDelete(p);
+  return link->icq_UDPSeqNum2-1;
+}
+
+WORD icq_UpdateMetaInfoHomepage(ICQLINK *link, unsigned char age, const char *homepage,
+                                unsigned char year, unsigned char month, unsigned char day,
+                                unsigned char lang1, unsigned char lang2, unsigned char lang3)
+{
+  icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_META_USER);
+  icq_PacketAppend16(p, META_CMD_SET_HOMEPAGE);
+  icq_PacketAppend8(p, age);
+  icq_PacketAppend16(p, 0x0200);
+  icq_PacketAppendString(p, homepage);
+  icq_PacketAppend8(p, year);
+  icq_PacketAppend8(p, month);
+  icq_PacketAppend8(p, day);
+  icq_PacketAppend8(p, 0xFF /* lang1 */);
+  icq_PacketAppend8(p, 0xFF /* lang2 */);
+  icq_PacketAppend8(p, 0xFF /* lang3 */);
+  icq_UDPSockWrite(link, p);
+  icq_PacketDelete(p);
+  return link->icq_UDPSeqNum2-1;
+}
+
+WORD icq_UpdateMetaInfoAbout(ICQLINK *link, const char *about)
+{
+  icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_META_USER);
+  icq_PacketAppend16(p, META_CMD_SET_ABOUT);
+  icq_PacketAppendString(p, about);
+  icq_UDPSockWrite(link, p);
+  icq_PacketDelete(p);
+  return link->icq_UDPSeqNum2-1;
+}
+
+WORD icq_UpdateMetaInfoSecurity(ICQLINK *link, unsigned char reqauth, unsigned char webpresence,
+                                unsigned char pubip)
+{
+  icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_META_USER);
+  icq_PacketAppend16(p, META_CMD_SET_SECURE);
+  icq_PacketAppend8(p, !reqauth);
+  icq_PacketAppend8(p, webpresence);
+  icq_PacketAppend8(p, pubip);
+  icq_UDPSockWrite(link, p);
+  icq_PacketDelete(p);
+  return link->icq_UDPSeqNum2-1;
+}
+
+WORD icq_UpdateNewUserInfo(ICQLINK *link, const char *nick, const char *first, const char *last,
+                           const char *email) /* V5 */
+{
+  icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_NEW_USER_INFO);
+  icq_PacketAppendString(p, nick);
+  icq_PacketAppendString(p, first);
+  icq_PacketAppendString(p, last);
+  icq_PacketAppendString(p, email);
+  icq_PacketAppend8(p, 1);
+  icq_PacketAppend8(p, 1);
+  icq_PacketAppend8(p, 1);
+  icq_UDPSockWrite(link, p);
+  icq_PacketDelete(p);
+  return link->icq_UDPSeqNum1-1;
+}
+
+WORD icq_SendMetaInfoReq(ICQLINK *link, unsigned long uin)
+{
+  icq_Packet *p = icq_UDPCreateStdPacket(link, UDP_CMD_META_USER);
+  icq_PacketAppend16(p, META_CMD_REQ_INFO);
+  icq_PacketAppend32(p, uin);
+  icq_UDPSockWrite(link, p);
+  icq_PacketDelete(p);
+  return link->icq_UDPSeqNum2-1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/udp.h	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,144 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+#ifndef _UDP_H_
+#define _UDP_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "icq.h"
+#include "util.h"
+#include "icqpacket.h"
+
+#define UDP_CMD_ACK                0x000A 
+#define UDP_CMD_SEND_THRU_SRV      0x010E
+#define UDP_CMD_LOGIN              0x03E8
+#define UDP_CMD_CONT_LIST          0x0406
+#define UDP_CMD_SEARCH_UIN         0x041A
+#define UDP_CMD_SEARCH_USER        0x0424
+#define UDP_CMD_KEEP_ALIVE         0x042E
+#define UDP_CMD_KEEP_ALIVE2        0x051E
+#define UDP_CMD_SEND_TEXT_CODE     0x0438
+#define UDP_CMD_LOGIN_1            0x044C
+#define UDP_CMD_INFO_REQ           0x0460
+#define UDP_CMD_EXT_INFO_REQ       0x046A
+#define UDP_CMD_CHANGE_PW          0x049C
+#define UDP_CMD_STATUS_CHANGE      0x04D8
+#define UDP_CMD_LOGIN_2            0x0528
+#define UDP_CMD_UPDATE_INFO        0x050A
+#define UDP_CMD_UPDATE_AUTH        0x0514
+#define UDP_CMD_UPDATE_EXT_INFO    0x04B0
+#define UDP_CMD_ADD_TO_LIST        0x053C
+#define UDP_CMD_REQ_ADD_LIST       0x0456
+#define UDP_CMD_QUERY_SERVERS      0x04BA
+#define UDP_CMD_QUERY_ADDONS       0x04C4
+#define UDP_CMD_NEW_USER_1         0x04EC
+#define UDP_CMD_NEW_USER_INFO      0x04A6
+#define UDP_CMD_ACK_MESSAGES       0x0442
+#define UDP_CMD_MSG_TO_NEW_USER    0x0456
+#define UDP_CMD_REG_NEW_USER       0x03FC
+#define UDP_CMD_VIS_LIST           0x06AE
+#define UDP_CMD_INVIS_LIST         0x06A4
+#define UDP_CMD_META_USER          0x064A
+#define UDP_CMD_RAND_SEARCH        0x056E
+#define UDP_CMD_RAND_SET           0x0564
+#define UDP_CMD_REVERSE_TCP_CONN   0x015E
+
+#define UDP_SRV_ACK                0x000A
+#define UDP_SRV_LOGIN_REPLY        0x005A
+#define UDP_SRV_USER_ONLINE        0x006E
+#define UDP_SRV_USER_OFFLINE       0x0078
+#define UDP_SRV_USER_FOUND         0x008C
+#define UDP_SRV_OFFLINE_MESSAGE    0x00DC
+#define UDP_SRV_END_OF_SEARCH      0x00A0
+#define UDP_SRV_INFO_REPLY         0x0118
+#define UDP_SRV_EXT_INFO_REPLY     0x0122
+#define UDP_SRV_STATUS_UPDATE      0x01A4
+#define UDP_SRV_X1                 0x021C
+#define UDP_SRV_X2                 0x00E6
+#define UDP_SRV_UPDATE             0x01E0
+#define UDP_SRV_UPDATE_EXT         0x00C8
+#define UDP_SRV_NEW_UIN            0x0046
+#define UDP_SRV_NEW_USER           0x00B4
+#define UDP_SRV_QUERY              0x0082
+#define UDP_SRV_SYSTEM_MESSAGE     0x01C2
+#define UDP_SRV_ONLINE_MESSAGE     0x0104
+#define UDP_SRV_GO_AWAY            0x00F0
+#define UDP_SRV_TRY_AGAIN          0x00FA
+#define UDP_SRV_FORCE_DISCONNECT   0x0028
+#define UDP_SRV_MULTI_PACKET       0x0212
+#define UDP_SRV_WRONG_PASSWORD     0x0064
+#define UDP_SRV_INVALID_UIN        0x012C
+#define UDP_SRV_META_USER          0x03DE
+#define UDP_SRV_RAND_USER          0x024E
+#define UDP_SRV_AUTH_UPDATE        0x01F4
+
+#define META_CMD_SET_INFO          1000
+#define META_CMD_SET_HOMEPAGE      1020
+#define META_CMD_SET_ABOUT         1030
+#define META_CMD_SET_SECURE        1060
+#define META_CMD_SET_PASS          1070
+#define META_CMD_REQ_INFO          1200
+#define META_SRV_RES_INFO          100
+#define META_SRV_RES_HOMEPAGE      120
+#define META_SRV_RES_ABOUT         130
+#define META_SRV_RES_SECURE        160
+#define META_SRV_RES_PASS          170
+#define META_SRV_USER_INFO         200
+#define META_SRV_USER_WORK         210
+#define META_SRV_USER_MORE         220
+#define META_SRV_USER_ABOUT        230
+#define META_SRV_USER_INTERESTS    240
+#define META_SRV_USER_AFFILIATIONS 250
+#define META_SRV_USER_HPCATEGORY   270
+#define META_SRV_USER_FOUND        410
+
+#define META_SRV_SUCCESS       10
+#define META_SRV_FAILURE       50
+
+#define TYPE_MSG               0x0001
+#define TYPE_CHAT              0x0002
+#define TYPE_FILE              0x0003
+#define TYPE_URL               0x0004
+#define TYPE_AUTH_REQ          0x0006
+#define TYPE_AUTH              0x0008
+#define TYPE_ADDED             0x000C
+#define TYPE_WEBPAGER          0x000D
+#define TYPE_EXPRESS           0x000E
+#define TYPE_CONTACT           0x0013
+#define TYPE_MASS_MASK         0x8000
+
+#define LOGIN_X1_DEF 0x00000098
+/*#define LOGIN_X1_DEF 0x000000D5*/
+#define LOGIN_X3_DEF 0x00000003
+/*#define LOGIN_X3_DEF 0x00000006*/
+#define LOGIN_X4_DEF 0x00000000
+#define LOGIN_X5_DEF 0x00980010
+/*#define LOGIN_X5_DEF 0x00D50008*/
+#define LOGIN_X6_DEF 0x00000050
+#define LOGIN_X7_DEF 0x00000003
+#define LOGIN_X8_DEF 0x00000000
+
+#define LOGIN_SNDONLY_TCP 0x02
+#define LOGIN_SNDRCV_TCP  0x04
+#define LOGIN_NO_TCP      0x06
+
+void icq_SendGotMessages(ICQLINK *link);
+void icq_SendLogin1(ICQLINK *link);
+void icq_StatusUpdate(ICQLINK *link, icq_Packet*);
+void icq_AckSrv(ICQLINK *link, int seq);
+void icq_HandleUserOffline(ICQLINK *link, icq_Packet*);
+void icq_HandleUserOnline(ICQLINK *link, icq_Packet*);
+void icq_DoMsg(ICQLINK *link, DWORD type, WORD len, char *data, DWORD uin,
+               BYTE hour, BYTE minute, BYTE day, BYTE month, WORD year);
+int icq_UDPSockWriteDirect(ICQLINK *link, icq_Packet*);
+int icq_UDPSockWrite(ICQLINK *link, icq_Packet*);
+int icq_UDPSockRead(ICQLINK *link, icq_Packet*);
+void icq_ServerResponse(ICQLINK *link, icq_Packet*);
+void icq_HandleMultiPacket(ICQLINK *link, icq_Packet*);
+
+void icq_UDPAck(ICQLINK *link, int seq);
+WORD icq_UDPSendMessage(ICQLINK *link, DWORD uin, const char *text);
+WORD icq_UDPSendURL(ICQLINK *link, DWORD uin, const char *url, const char *descr);
+
+#endif /* _UDP_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/udphandle.c	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,887 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+$Id: udphandle.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Log$
+Revision 1.1  2000/11/28 02:22:42  warmenhoven
+icq. whoop de doo
+
+Revision 1.28  2000/06/25 17:25:52  denis
+icq_HandleMetaUserInfo() handles all (!) available in original icq2k
+Meta User Info packets along with other useful Meta* packets. (WOW! ;)
+
+Revision 1.27  2000/05/10 18:54:43  denis
+icq_Disconnect() now called before icq_Disconnected callback to
+prevent high CPU usage in kicq's "reconnect on disconnect" code.
+
+Revision 1.26  2000/05/03 18:29:15  denis
+Callbacks have been moved to the ICQLINK structure.
+
+Revision 1.25  2000/02/07 02:48:15  bills
+changed log message in HandleUserOnline
+
+Revision 1.24  2000/01/16 03:59:10  bills
+reworked list code so list_nodes don't need to be inside item structures,
+removed strlist code and replaced with generic list calls
+
+Revision 1.23  1999/12/27 11:12:37  denis
+icq_UpdateMetaInfoSecurity() added for setting "My authorization is
+required", "Web Aware" and "IP Publishing".
+
+Revision 1.22  1999/12/14 03:37:06  bills
+removed old real_ip->ip masq hack, added store to remote_real_ip in
+icq_ContactItem
+
+Revision 1.21  1999/12/12 18:03:58  denis
+Authorization Request packet handling fixed.
+
+Revision 1.20  1999/11/29 17:18:31  denis
+icq_DoMsg() redone using string lists.
+
+Revision 1.18  1999/11/11 15:10:32  guruz
+- Added Base for Webpager Messages. Please type "make fixme"
+- Removed Segfault when kicq is started the first time
+
+Revision 1.17  1999/10/14 11:44:04  denis
+Cleanups.
+
+Revision 1.16  1999/09/29 17:16:08  denis
+MailExpress message handler started.
+
+Revision 1.15  1999/07/18 20:23:54  bills
+fixed tcp port bug in icq_HandleUserOnline, changed to use new byte-order
+& contact list functions
+
+Revision 1.14  1999/07/16 15:46:02  denis
+Cleaned up.
+
+Revision 1.13  1999/07/16 12:40:55  denis
+ICQ UDP v5 implemented.
+Encription for ICQ UDP v5 implemented.
+icq_Packet* unified interface for UDP packets implemented.
+Multipacket support of ICQ UDP v5 support added.
+
+Revision 1.12  1999/07/12 15:13:45  cproch
+- added definition of ICQLINK to hold session-specific global variabled
+  applications which have more than one connection are now possible
+- changed nearly every function defintion to support ICQLINK parameter
+
+Revision 1.11  1999/07/03 06:46:54  lord
+converting icq_userOnline callback parameters to correct
+byte order.
+
+Revision 1.10  1999/07/03 02:29:46  bills
+added code to HandleUserOnline to update tcp_flag
+
+Revision 1.9  1999/04/29 09:40:54  denis
+Unsuccessful attempt to implement web presence (webaware) feature
+
+Revision 1.8  1999/04/18 01:58:37  bills
+changed icq_SrvAck call to icq_RequestNotify
+
+Revision 1.7  1999/04/17 19:26:49  bills
+removed *_link entries from icq_ContactItem, including cleaup/init code
+
+Revision 1.6  1999/04/14 15:05:39  denis
+Cleanups for "strict" compiling (-ansi -pedantic)
+Switched from icq_Log callback to icq_Fmt function.
+
+Revision 1.5  1999/04/05 18:47:23  bills
+initial chat support implemented
+
+Revision 1.4  1999/03/31 01:39:50  bills
+added handling of tcp_flag in HandleLogin
+
+Revision 1.3  1999/03/28 03:35:17  bills
+fixed function names so icqlib compiles, fixed bug in HandleUserOnline
+(remote_ip and remote_real_ip were not evaluating correctly), added
+hack so I can test using local network
+
+Revision 1.2  1999/03/25 22:25:02  bills
+modified icq_HandleUserOnline & Offline for new message_link
+
+Revision 1.1  1999/03/24 11:37:38  denis
+Underscored files with TCP stuff renamed.
+TCP stuff cleaned up
+Function names changed to corresponding names.
+icqlib.c splitted to many small files by subject.
+C++ comments changed to ANSI C comments.
+
+*/
+
+#include <stdlib.h>
+
+#include "icqtypes.h"
+#include "icq.h"
+#include "icqlib.h"
+#include "udp.h"
+#include "icqpacket.h"
+#include "queue.h"
+#include "icqbyteorder.h"
+#include "list.h"
+
+int icq_SplitFields(list *strList, const char *str)
+{
+  char *tmpBuf, *tmp, *ptr;
+  int count = 0;
+
+  tmpBuf = (char*)malloc(strlen(str)+1);
+  strcpy(tmpBuf, str);
+  ptr = tmpBuf;
+
+  while(ptr)
+  {
+    char *p;
+    tmp = strchr(ptr, 0xFE);
+    if(tmp != 0L)
+    {
+      *tmp = 0;
+      tmp++;
+    }
+    count++;
+    p = (char *)malloc(strlen(ptr)+1);
+    strcpy(p, ptr);
+    list_enqueue(strList, p);
+    ptr = tmp;
+  }
+
+  free(tmpBuf);
+  return count;
+}
+
+void icq_DoMsg(ICQLINK *link, DWORD type, WORD len, char *data, DWORD uin, BYTE hour,
+               BYTE minute, BYTE day, BYTE month, WORD year)
+{
+  list *strList;
+
+  strList = list_new();
+  switch(type)
+  {
+    case TYPE_ADDED:
+      /* Format: Nick, 0xFE, FName, 0xFE, LName, 0xFE, EMail */
+      if(icq_SplitFields(strList, data)!=4)
+      {
+        icq_FmtLog(link, ICQ_LOG_ERROR, "Bad packet!\n");
+        return;
+      }
+      icq_RusConv("wk", list_at(strList, 0)); /* Nick */
+      icq_RusConv("wk", list_at(strList, 1)); /* FName */
+      icq_RusConv("wk", list_at(strList, 2)); /* LName */
+      icq_RusConv("wk", list_at(strList, 3)); /* EMail */
+      icq_FmtLog(link, ICQ_LOG_MESSAGE, "%lu has added you to their contact list, "
+                 "Nick: %s, First Name: %s, Last Name: %s, EMail: %s\n",
+                 uin, list_at(strList, 0), list_at(strList, 1),
+                 list_at(strList, 2), list_at(strList, 3));
+      if(link->icq_RecvAdded)
+        (*link->icq_RecvAdded)(link, uin, hour, minute, day, month, year,
+                         list_at(strList, 0), list_at(strList, 1),
+                         list_at(strList, 2), list_at(strList, 3));
+      break;
+    case TYPE_AUTH_REQ:
+      /* Format: Nick, 0xFE, FName, 0xFE, LName, 0xFE, EMail, 0xFE, 0, 0xFE, Reason */
+      if(icq_SplitFields(strList, data)!=6)
+      {
+        icq_FmtLog(link, ICQ_LOG_ERROR, "Bad packet!\n");
+        return;
+      }
+      icq_RusConv("wk", list_at(strList, 0)); /* Nick */
+      icq_RusConv("wk", list_at(strList, 1)); /* FName */
+      icq_RusConv("wk", list_at(strList, 2)); /* LName */
+      icq_RusConv("wk", list_at(strList, 3)); /* EMail */
+      icq_RusConv("wk", list_at(strList, 5)); /* Reason */
+      icq_FmtLog(link, ICQ_LOG_MESSAGE, "%lu has requested your authorization to be added to "
+                 "their contact list, Nick: %s, First Name: %s, Last Name: %s, "
+                 "EMail: %s, Reason: %s\n", uin, list_at(strList, 0), list_at(strList, 1),
+                 list_at(strList, 2), list_at(strList, 3), list_at(strList, 4));
+      if(link->icq_RecvAuthReq)
+        (*link->icq_RecvAuthReq)(link, uin, hour, minute, day, month, year, list_at(strList, 0),
+                           list_at(strList, 1), list_at(strList, 2),
+                           list_at(strList, 3), list_at(strList, 5));
+      break;
+    case TYPE_URL:
+      /* Format: Description, 0xFE, URL */
+      if(icq_SplitFields(strList, data)!=2)
+      {
+        icq_FmtLog(link, ICQ_LOG_ERROR, "Bad packet!\n");
+        return;
+      }
+      icq_RusConv("wk", list_at(strList, 0)); /* Description */
+      icq_FmtLog(link, ICQ_LOG_MESSAGE, "URL received from %lu, URL: %s, Description: %s\n",
+                 uin, list_at(strList, 1), list_at(strList, 0));
+      if(link->icq_RecvURL)
+        (*link->icq_RecvURL)(link, uin, hour, minute, day, month, year, list_at(strList, 1),
+                       list_at(strList, 0));
+      break;
+    case TYPE_WEBPAGER:
+      /* Format: Nick, 0xFE, Empty-FName, 0xFE, Empty-LName, 0xFE, EMail, 0xFE,
+       *         Reason(3), 0xFE, Message with IP & Subject */
+      if(icq_SplitFields(strList, data)!=6)
+      {
+        icq_FmtLog(link, ICQ_LOG_ERROR, "Bad packet!\n");
+        return;
+      }
+      icq_RusConv("wk", list_at(strList, 0)); /* Nick */
+      icq_RusConv("wk", list_at(strList, 5)); /* Message */
+      icq_FmtLog(link, ICQ_LOG_MESSAGE, "WebPager message received, Nick: %s, EMail: %s, "
+                 "Message:\n%s\n", list_at(strList, 0), list_at(strList, 3),
+                 list_at(strList, 5));
+      if(link->icq_RecvWebPager)
+        (*link->icq_RecvWebPager)(link, hour, minute, day, month, year, list_at(strList, 0),
+                                   list_at(strList, 3), list_at(strList, 5));
+      break;
+    case TYPE_EXPRESS:
+      /* Format: Nick, 0xFE, Empty-FName, 0xFE, Empty-LName, 0xFE, EMail, 0xFE,
+       *         Reason(3), 0xFE, Message Subject */
+      if(icq_SplitFields(strList, data)!=6)
+      {
+        icq_FmtLog(link, ICQ_LOG_ERROR, "Bad packet!\n");
+        return;
+      }
+      icq_RusConv("wk", list_at(strList, 0)); /* Nick */
+      icq_RusConv("wk", list_at(strList, 5)); /* Message */
+      icq_FmtLog(link, ICQ_LOG_MESSAGE, "MailExpress message received, Nick: %s, EMail: %s, "
+                 "Message:\n%s\n", list_at(strList, 0), list_at(strList, 3),
+                 list_at(strList, 5));
+      if(link->icq_RecvMailExpress)
+        (*link->icq_RecvMailExpress)(link, hour, minute, day, month, year, list_at(strList, 0),
+                               list_at(strList, 3), list_at(strList, 5));
+      break;
+    default:
+      icq_RusConv("wk", data); /* Entire message */
+      icq_FmtLog(link, ICQ_LOG_MESSAGE, "Instant message type %i from %lu:\n%s\n", type, uin, data);
+      if(link->icq_RecvMessage)
+        (*link->icq_RecvMessage)(link, uin, hour, minute, day, month, year, data);
+  }
+  list_delete(strList, free);
+}
+
+void icq_HandleInfoReply(ICQLINK *link, icq_Packet *p)
+{
+  char *ptr1, *ptr2, *ptr3, *ptr4;
+  DWORD uin;
+  icq_PacketGotoUDPInData(p, 0);
+  uin = icq_PacketRead32(p);
+  ptr1 = icq_PacketReadStringNew(p);
+  ptr2 = icq_PacketReadStringNew(p);
+  ptr3 = icq_PacketReadStringNew(p);
+  ptr4 = icq_PacketReadStringNew(p);
+  icq_RusConv("wk", ptr1);
+  icq_RusConv("wk", ptr2);
+  icq_RusConv("wk", ptr3);
+  icq_RusConv("wk", ptr4);
+  icq_FmtLog(link, ICQ_LOG_MESSAGE, "Info reply for %lu\n", uin);
+  if(link->icq_InfoReply)
+    (*link->icq_InfoReply)(link, uin, ptr1, ptr2, ptr3, ptr4, icq_PacketRead8(p));
+  icq_UDPAck(link, icq_PacketReadUDPInSeq1(p));
+  free(ptr1);
+  free(ptr2);
+  free(ptr3);
+  free(ptr4);
+}
+
+void icq_HandleExtInfoReply(ICQLINK *link, icq_Packet *p)
+{
+  char *ptr1, *ptr2, *ptr3, *ptr4, *ptr5;
+  DWORD uin;
+  WORD cnt_code, age;
+  char cnt_stat, gender;
+
+  icq_PacketGotoUDPInData(p, 0);
+  uin = icq_PacketRead32(p);
+  ptr1 = icq_PacketReadStringNew(p);
+  cnt_code = icq_PacketRead16(p);
+  cnt_stat = icq_PacketRead8(p);
+  ptr2 = icq_PacketReadStringNew(p);
+  age = icq_PacketRead16(p);
+  gender = icq_PacketRead8(p);
+  ptr3 = icq_PacketReadStringNew(p);
+  ptr4 = icq_PacketReadStringNew(p);
+  ptr5 = icq_PacketReadStringNew(p);
+  icq_RusConv("wk", ptr1);
+  icq_RusConv("wk", ptr2);
+  icq_RusConv("wk", ptr3);
+  icq_RusConv("wk", ptr4);
+  icq_RusConv("wk", ptr5);
+  icq_FmtLog(link, ICQ_LOG_MESSAGE, "Extended info reply for %lu\n", uin);
+  if(link->icq_ExtInfoReply)
+    (*link->icq_ExtInfoReply)(link, uin, (char*)ptr1, cnt_code, cnt_stat, (char*)ptr2, age,
+                              gender, (char*)ptr3, (char*)ptr4, (char*)ptr5);
+  icq_UDPAck(link, icq_PacketReadUDPInSeq1(p));
+  free(ptr1);
+  free(ptr2);
+  free(ptr3);
+  free(ptr4);
+  free(ptr5);
+}
+
+void icq_HandleSearchReply(ICQLINK *link, icq_Packet *p)
+{
+  char *ptr1, *ptr2, *ptr3, *ptr4, auth;
+  DWORD uin;
+  icq_PacketGotoUDPInData(p, 0);
+  uin = icq_PacketRead32(p);
+  ptr1 = icq_PacketReadStringNew(p);
+  ptr2 = icq_PacketReadStringNew(p);
+  ptr3 = icq_PacketReadStringNew(p);
+  ptr4 = icq_PacketReadStringNew(p);
+  icq_RusConv("wk", ptr1);
+  icq_RusConv("wk", ptr2);
+  icq_RusConv("wk", ptr3);
+  icq_RusConv("wk", ptr4);
+  auth = icq_PacketRead8(p);
+  icq_FmtLog(link, ICQ_LOG_MESSAGE, "User found %lu, Nick: %s, First Name: %s, Last Name: %s, "
+             "EMail: %s, Auth: %s\n", uin, ptr1, ptr2, ptr3, ptr4, auth==1?"no":"yes");
+  if(link->icq_UserFound)
+    (*link->icq_UserFound)(link, uin, (char*)ptr1, (char*)ptr2, (char*)ptr3, (char*)ptr4, auth);
+  icq_UDPAck(link, icq_PacketReadUDPInSeq1(p));
+  free(ptr1);
+  free(ptr2);
+  free(ptr3);
+  free(ptr4);
+}
+
+/************************************************
+This is called when a user goes offline
+*************************************************/
+void icq_HandleUserOffline(ICQLINK *link, icq_Packet *p)
+{
+  DWORD remote_uin;
+  icq_ContactItem *ptr;
+
+  icq_PacketGotoUDPInData(p, 0);
+  remote_uin = icq_PacketRead32(p);
+  icq_FmtLog(link, ICQ_LOG_MESSAGE, "User %lu logged off\n", remote_uin);
+  if(link->icq_UserOffline)
+    (*link->icq_UserOffline)(link, remote_uin);
+
+  ptr=icq_ContactFind(link, remote_uin);
+  if(ptr)
+  {
+    ptr->remote_ip = 0;
+    ptr->remote_port = 0;
+  }
+  icq_UDPAck(link, icq_PacketReadUDPInSeq1(p));
+}
+
+void icq_HandleUserOnline(ICQLINK *link, icq_Packet *p)
+{
+  DWORD remote_uin, new_status, remote_ip, remote_real_ip;
+  DWORD remote_port; /* Why Mirabilis used 4 bytes for port? */
+  BYTE tcp_flag;
+  icq_ContactItem *ptr;
+
+  icq_PacketGotoUDPInData(p, 0);
+  remote_uin = icq_PacketRead32(p);
+  remote_ip = ntohl(icq_PacketRead32n(p));  /* icqtohl() */
+  remote_port = icqtohl(icq_PacketRead32n(p));
+  remote_real_ip = ntohl(icq_PacketRead32n(p)); /* icqtohl() */
+  tcp_flag = icq_PacketRead8(p);
+  new_status = icq_PacketRead32(p);
+
+  icq_FmtLog(link, ICQ_LOG_MESSAGE,
+             "User %lu (%s = 0x%X) logged on. tcp_flag=0x%X IP=%08X, real IP=%08X, port=%d\n",
+             remote_uin, icq_ConvertStatus2Str(new_status), new_status, tcp_flag, remote_ip,
+             remote_real_ip, remote_port);
+  if(link->icq_UserOnline)
+    (*link->icq_UserOnline)(link, remote_uin, new_status, remote_ip, remote_port, remote_real_ip, tcp_flag);
+
+  ptr=icq_ContactFind(link, remote_uin);
+  if(ptr)
+  {
+    ptr->remote_ip=remote_ip;
+    ptr->remote_real_ip=remote_real_ip;
+    ptr->remote_port = remote_port;
+    ptr->tcp_flag = tcp_flag;
+  }
+  icq_UDPAck(link, icq_PacketReadUDPInSeq1(p));
+}
+
+void icq_HandleStatusChange(ICQLINK *link, icq_Packet *p)
+{
+  unsigned long remote_uin, new_status;
+
+  icq_PacketGotoUDPInData(p, 0);
+  remote_uin = icq_PacketRead32(p);
+  new_status = icq_PacketRead32(p);
+  icq_FmtLog(link, ICQ_LOG_MESSAGE, "%lu changed status to %s (0x%X)\n", remote_uin,
+             icq_ConvertStatus2Str(new_status), new_status);
+  if(link->icq_UserStatusUpdate)
+    (*link->icq_UserStatusUpdate)(link, remote_uin, new_status);
+  icq_UDPAck(link, icq_PacketReadUDPInSeq1(p));
+}
+
+void icq_HandleMetaUserInfo(ICQLINK *link, icq_Packet *p)
+{
+  unsigned short subcmd, country, seq2, age, occupation, wcountry;
+  unsigned char res, auth, timezone, webaware, hideip, gender;
+  unsigned char *nick, *first, *last, *email, *about, *city;
+  unsigned char *pri_eml, *sec_eml, *old_eml;
+  unsigned char *phone, *fax, *street, *cellular, *state;
+  unsigned char *wcity, *wstate, *wphone, *wfax, *waddress;
+  unsigned char *company, *department, *job, *whomepage;
+  unsigned char *homepage;
+  unsigned char byear, bmonth, bday, lang1, lang2, lang3, inum, i;
+  unsigned char anum, bnum, hnum;
+  unsigned long uin, zip, wzip;
+  unsigned char *empty = "";
+  unsigned char *interests[4] = {0, 0, 0, 0};
+  unsigned short icategory[4] = {0, 0, 0, 0};
+  unsigned char *affiliations[4] = {0, 0, 0, 0};
+  unsigned short acategory[4] = {0, 0, 0, 0};
+  unsigned char *backgrounds[4] = {0, 0, 0, 0};
+  unsigned short bcategory[4] = {0, 0, 0, 0};
+  unsigned char *hpcat[4] = {0, 0, 0, 0};
+  unsigned short hcategory[4] = {0, 0, 0, 0};
+
+  seq2 = icq_PacketReadUDPInSeq2(p);
+  icq_PacketGotoUDPInData(p, 0);
+  subcmd = icq_PacketRead16(p);
+  res = icq_PacketRead8(p);
+  if(res == META_SRV_FAILURE)
+  {
+    icq_FmtLog(link, ICQ_LOG_WARNING, "META failure\n");
+    if(link->icq_RequestNotify)
+      (*link->icq_RequestNotify)(link, seq2, ICQ_NOTIFY_FAILED, sizeof(subcmd), &subcmd);
+  }
+  else
+    switch(subcmd)
+    {
+      case META_SRV_USER_FOUND:
+        uin = icq_PacketRead32(p);
+        nick = icq_PacketReadStringNew(p);
+        first = icq_PacketReadStringNew(p);
+        last = icq_PacketReadStringNew(p);
+        email = icq_PacketReadStringNew(p);
+        auth = icq_PacketRead8(p);
+        icq_PacketRead16(p); // ???
+        icq_PacketRead32(p); // ???
+        icq_RusConv("wk", nick);
+        icq_RusConv("wk", first);
+        icq_RusConv("wk", last);
+        icq_RusConv("wk", email);
+        icq_FmtLog(link, ICQ_LOG_MESSAGE, "META User Found %lu, Nick: %s, First Name: %s, "\
+                   "Last Name: %s, EMail: %s, Auth: %s\n", seq2, uin, nick, first, last,
+                   email, auth==1?"no":"yes");
+        if(link->icq_MetaUserFound)
+          (*link->icq_MetaUserFound)(link, seq2, uin, nick, first, last, email, auth);
+        free(nick);
+        free(first);
+        free(last);
+        free(email);
+        break;
+      case META_SRV_USER_INFO: // finished!
+        nick = icq_PacketReadStringNew(p);
+        first = icq_PacketReadStringNew(p);
+        last = icq_PacketReadStringNew(p);
+        pri_eml = icq_PacketReadStringNew(p);
+        sec_eml = icq_PacketReadStringNew(p);
+        old_eml = icq_PacketReadStringNew(p);
+        city = icq_PacketReadStringNew(p);
+        state = icq_PacketReadStringNew(p);
+        phone = icq_PacketReadStringNew(p);
+        fax = icq_PacketReadStringNew(p);
+        street = icq_PacketReadStringNew(p);
+        cellular = icq_PacketReadStringNew(p);
+        zip = icq_PacketRead32(p);
+        country = icq_PacketRead16(p);
+        timezone = icq_PacketRead8(p);         // +1 = -30min, -1 = +30min (-4 = GMT+0200)
+        auth = icq_PacketRead8(p);             // 1 - no auth required, 0 - required
+        webaware = icq_PacketRead8(p);         // 1 - yes, 0 - no
+        hideip = icq_PacketRead8(p);           // 1 - yes, 0 - no
+        icq_RusConv("wk", nick);
+        icq_RusConv("wk", first);
+        icq_RusConv("wk", last);
+        icq_RusConv("wk", pri_eml);
+        icq_RusConv("wk", sec_eml);
+        icq_RusConv("wk", old_eml);
+        icq_RusConv("wk", city);
+        icq_RusConv("wk", state);
+        icq_RusConv("wk", phone);
+        icq_RusConv("wk", fax);
+        icq_RusConv("wk", street);
+        icq_RusConv("wk", cellular);
+        icq_FmtLog(link, ICQ_LOG_MESSAGE, "META User Info: %s, %s, %s, "\
+                   "%s, %s, %s, %s, %s, %s, %s, %s, %s, %lu, %s, %i, %s, %s, %s\n",
+                   nick, first, last, pri_eml, sec_eml, old_eml, city, state, phone,
+                   fax, street, cellular, zip, icq_GetCountryName(country), timezone,
+                   auth?"false":"true", webaware?"true":"false", hideip?"true":"false");
+        if(link->icq_MetaUserInfo)
+          (*link->icq_MetaUserInfo)(link, seq2, nick, first, last, pri_eml, sec_eml,
+                                    old_eml, city, state, phone, fax, street, cellular,
+                                    zip, country, timezone, auth, webaware, hideip);
+        free(nick);
+        free(first);
+        free(last);
+        free(pri_eml);
+        free(sec_eml);
+        free(old_eml);
+        free(city);
+        free(state);
+        free(phone);
+        free(fax);
+        free(street);
+        free(cellular);
+        break;
+      case META_SRV_USER_WORK: // finished!
+        wcity = icq_PacketReadStringNew(p);
+        wstate = icq_PacketReadStringNew(p);
+        wphone = icq_PacketReadStringNew(p);
+        wfax = icq_PacketReadStringNew(p);
+        waddress = icq_PacketReadStringNew(p);
+        wzip = icq_PacketRead32(p);
+        wcountry = icq_PacketRead16(p);          // icq_GetCountryName()
+        company = icq_PacketReadStringNew(p);
+        department = icq_PacketReadStringNew(p);
+        job = icq_PacketReadStringNew(p);
+        occupation = icq_PacketRead16(p);        // icq_GetMetaOccupationName()
+        whomepage = icq_PacketReadStringNew(p);
+        icq_RusConv("wk", wcity);
+        icq_RusConv("wk", wstate);
+        icq_RusConv("wk", wphone);
+        icq_RusConv("wk", wfax);
+        icq_RusConv("wk", waddress);
+        icq_RusConv("wk", company);
+        icq_RusConv("wk", department);
+        icq_RusConv("wk", job);
+        icq_RusConv("wk", whomepage);
+        icq_FmtLog(link, ICQ_LOG_MESSAGE, "META User Work: %s, %s, %s, "\
+                   "%s, %s,   %lu, %s, %s, %s, %s, %s, %s\n", wcity, wstate,
+                   wphone, wfax, waddress, wzip, icq_GetCountryName(wcountry),
+                   company, department, job, icq_GetMetaOccupationName(occupation),
+                   whomepage);
+        if(link->icq_MetaUserWork)
+          (*link->icq_MetaUserWork)(link, seq2, wcity, wstate, wphone, wfax,
+                                    waddress, wzip, wcountry, company, department,
+                                    job, occupation, whomepage);
+        free(wcity);
+        free(wstate);
+        free(wphone);
+        free(wfax);
+        free(waddress);
+        free(company);
+        free(department);
+        free(job);
+        free(whomepage);
+        break;
+      case META_SRV_USER_MORE: // finished!
+        age = icq_PacketRead16(p);    // 0xFFFF - not entered
+        gender = icq_PacketRead8(p);  // 1 - female, 2 - male
+        homepage = icq_PacketReadStringNew(p);
+        byear = icq_PacketRead8(p);   // starting from 1900
+        bmonth = icq_PacketRead8(p);
+        bday = icq_PacketRead8(p);
+        lang1 = icq_PacketRead8(p);   // icq_GetMetaLanguageName()
+        lang2 = icq_PacketRead8(p);   // icq_GetMetaLanguageName()
+        lang3 = icq_PacketRead8(p);   // icq_GetMetaLanguageName()
+        icq_RusConv("wk", homepage);
+        icq_FmtLog(link, ICQ_LOG_MESSAGE, "META User More: %i, %s, %s, "\
+                   "%02i/%02i/%04i, %s, %s, %s\n", age,
+                   gender==1?"female":gender==2?"male":"not entered",
+                   homepage, bday, bmonth, byear+1900, icq_GetMetaLanguageName(lang1),
+                   icq_GetMetaLanguageName(lang2), icq_GetMetaLanguageName(lang3));
+        if(link->icq_MetaUserMore)
+          (*link->icq_MetaUserMore)(link, seq2, age, gender, homepage, byear,
+                                    bmonth, bday, lang1, lang2, lang3);
+        free(homepage);
+        break;
+      case META_SRV_USER_ABOUT: // finished!
+        about = icq_PacketReadStringNew(p);
+        icq_RusConv("wk", about);
+        icq_FmtLog(link, ICQ_LOG_MESSAGE, "META User About: %s\n", about);
+        if(link->icq_MetaUserAbout)
+          (*link->icq_MetaUserAbout)(link, seq2, about);
+        free(about);
+        break;
+      case META_SRV_USER_INTERESTS: // finished!
+        inum = icq_PacketRead8(p);
+        for(i=0; i<inum && i<4; i++)
+        {
+          icategory[i] = icq_PacketRead16(p);
+          interests[i] = icq_PacketReadStringNew(p);
+          icq_RusConv("wk", interests[i]);
+        }
+        icq_FmtLog(link, ICQ_LOG_MESSAGE, "META User Interests: %i, %i - %s, "\
+                   "%i - %s, %i - %s, %i - %s\n", inum, icategory[0],
+                   interests[0]?interests[0]:empty, icategory[1], interests[1]?interests[1]:empty,
+                   icategory[2], interests[2]?interests[2]:empty, icategory[3],
+                   interests[3]?interests[3]:empty);
+        if(link->icq_MetaUserInterests)
+          (*link->icq_MetaUserInterests)(link, seq2, inum, icategory[0], interests[0],
+                                         icategory[1], interests[1], icategory[2],
+                                         interests[2], icategory[3], interests[3]);
+        for(i=0; i<inum && i<4; i++)
+          free(interests[i]);
+        break;
+      case META_SRV_USER_AFFILIATIONS: // finished!
+        bnum = icq_PacketRead8(p);
+        for(i=0; i<bnum && i<4; i++)
+        {
+          bcategory[i] = icq_PacketRead16(p);           // icq_GetMetaBackgroundName()
+          backgrounds[i] = icq_PacketReadStringNew(p);
+          icq_RusConv("wk", backgrounds[i]);
+        }
+        anum = icq_PacketRead8(p);
+        for(i=0; i<anum && i<4; i++)
+        {
+          acategory[i] = icq_PacketRead16(p);           // icq_GetMetaAffiliationName()
+          affiliations[i] = icq_PacketReadStringNew(p);
+          icq_RusConv("wk", affiliations[i]);
+        }
+        icq_FmtLog(link, ICQ_LOG_MESSAGE, "META User Affiliations: %i, %s - %s, "\
+                   "%s - %s, %s - %s, %s - %s; Backgrounds: %i, %s - %s, %s - %s, "\
+                   "%s - %s, %s - %s\n", anum,
+                   icq_GetMetaAffiliationName(acategory[0]), affiliations[0]?affiliations[0]:empty,
+                   icq_GetMetaAffiliationName(acategory[1]), affiliations[1]?affiliations[1]:empty,
+                   icq_GetMetaAffiliationName(acategory[2]), affiliations[2]?affiliations[2]:empty,
+                   icq_GetMetaAffiliationName(acategory[3]), affiliations[3]?affiliations[3]:empty,
+                   bnum, icq_GetMetaBackgroundName(bcategory[0]), backgrounds[0]?backgrounds[0]:empty,
+                   icq_GetMetaBackgroundName(bcategory[1]), backgrounds[1]?backgrounds[1]:empty,
+                   icq_GetMetaBackgroundName(bcategory[2]), backgrounds[2]?backgrounds[2]:empty,
+                   icq_GetMetaBackgroundName(bcategory[3]), backgrounds[3]?backgrounds[3]:empty);
+        if(link->icq_MetaUserAffiliations)
+          (*link->icq_MetaUserAffiliations)(link, seq2, anum, acategory[0],
+                  affiliations[0], acategory[1], affiliations[1], acategory[2],
+                  affiliations[2], acategory[3], affiliations[3], bnum,
+                  bcategory[0], backgrounds[0], bcategory[1], backgrounds[1],
+                  bcategory[2], backgrounds[2], bcategory[3], backgrounds[3]);
+        for(i=0; i<bnum && i<4; i++)
+          free(backgrounds[i]);
+        for(i=0; i<anum && i<4; i++)
+          free(affiliations[i]);
+        break;
+      case META_SRV_USER_HPCATEGORY: // finished!
+        hnum = icq_PacketRead8(p);
+        for(i=0; i<hnum && i<1; i++)
+        {
+          hcategory[i] = icq_PacketRead16(p);
+          hpcat[i] = icq_PacketReadStringNew(p);
+          icq_RusConv("wk", hpcat[i]);
+        }
+        icq_FmtLog(link, ICQ_LOG_MESSAGE, "META User Homepage Category: %i, %i - %s\n",
+                   hnum, hcategory[0], hpcat[0]);
+        if(link->icq_MetaUserHomePageCategory)
+          (*link->icq_MetaUserHomePageCategory)(link, seq2, hnum, hcategory[0], hpcat[0]?hpcat[0]:empty);
+        for(i=0; i<hnum && i<1; i++)
+          free(hpcat[i]);
+        break;
+      case META_SRV_RES_INFO:
+      case META_SRV_RES_HOMEPAGE:
+      case META_SRV_RES_ABOUT:
+      case META_SRV_RES_SECURE:
+      case META_SRV_RES_PASS:
+        icq_FmtLog(link, ICQ_LOG_MESSAGE, "META success\n");
+        if(link->icq_RequestNotify)
+          (*link->icq_RequestNotify)(link, seq2, ICQ_NOTIFY_SUCCESS, sizeof(subcmd), &subcmd);
+        break;
+      default:
+        icq_FmtLog(link, ICQ_LOG_MESSAGE, "META User - 0x%04X\n", subcmd);
+        icq_PacketUDPDump(p);
+        break;
+    }
+  icq_UDPAck(link, icq_PacketReadUDPInSeq1(p));
+}
+
+void icq_HandleMultiPacket(ICQLINK *link, icq_Packet *p)
+{
+  icq_Packet *tmp;
+  int num, i;
+  icq_PacketGotoUDPInData(p, 0);
+  num = icq_PacketRead8(p);
+
+  icq_FmtLog(link, ICQ_LOG_MESSAGE, "MultiPacket: %i packets\n", num);
+
+  for(i = 0; i < num; i++)
+  {
+    tmp = icq_PacketNew();
+    tmp->length = icq_PacketRead16(p);
+    memcpy(tmp->data, &(p->data[p->cursor]), tmp->length);
+    icq_PacketAdvance(p, tmp->length);
+    icq_ServerResponse(link, tmp);
+    icq_PacketDelete(tmp);
+  }
+}
+
+void icq_ServerResponse(ICQLINK *link, icq_Packet *p)
+{
+  time_t cur_time;
+  struct tm *tm_str;
+  int len;
+  struct in_addr in_a;
+  DWORD uin;
+  WORD year, type, seq, cmd;
+  BYTE month, day, hour, minute;
+
+  seq = icq_PacketReadUDPInSeq1(p);
+  cmd = icq_PacketReadUDPInCmd(p);
+
+  if(icq_PacketReadUDPInVer(p) == 5) /* We understand only V5 packets! */
+  {
+    switch(cmd)
+    {
+      case UDP_SRV_ACK:
+        icq_FmtLog(link, ICQ_LOG_MESSAGE, "The server acknowledged the command\n");
+        if(link->icq_RequestNotify)
+        {
+          (*link->icq_RequestNotify)(link, seq, ICQ_NOTIFY_ACK, 0, 0);
+          (*link->icq_RequestNotify)(link, seq, ICQ_NOTIFY_SUCCESS, 0, 0);
+        }
+        icq_UDPQueueDelSeq(link, seq);
+        if(link->icq_SetTimeout)
+          link->icq_SetTimeout(link, icq_UDPQueueInterval(link));
+        break;
+      case UDP_SRV_MULTI_PACKET:
+        icq_HandleMultiPacket(link, p);
+        break;
+      case UDP_SRV_NEW_UIN:
+        uin = icq_PacketReadUDPInUIN(p);
+        icq_FmtLog(link, ICQ_LOG_MESSAGE, "The new uin is %lu\n", uin);
+        icq_UDPAck(link, seq);
+        if(link->icq_NewUIN)
+          (*link->icq_NewUIN)(link, uin);
+        break;
+      case UDP_SRV_LOGIN_REPLY:
+        icq_PacketGotoUDPInData(p, 0);
+        link->icq_OurIP = ntohl(icq_PacketRead32n(p));
+/*       icq_OurIp = icq_PacketRead32(p); */
+        in_a.s_addr = htonl(link->icq_OurIP);
+        icq_FmtLog(link, ICQ_LOG_MESSAGE, "Login successful, UIN: %lu, IP: %s\n",
+                   link->icq_Uin, inet_ntoa(in_a));
+        icq_UDPAck(link, seq);
+        icq_SendLogin1(link);
+        icq_SendContactList(link);
+        icq_SendVisibleList(link);
+        if(link->icq_Logged)
+          (*link->icq_Logged)(link);
+        break;
+      case UDP_SRV_OFFLINE_MESSAGE: /* Offline message through the server */
+        icq_PacketGotoUDPInData(p, 0);
+        uin = icq_PacketRead32(p);
+        year = icq_PacketRead16(p);
+        month = icq_PacketRead8(p);
+        day = icq_PacketRead8(p);
+        hour = icq_PacketRead8(p);
+        minute = icq_PacketRead8(p);
+        type = icq_PacketRead16(p);
+        len = icq_PacketRead16(p);
+        icq_DoMsg(link, type, len, (char*)&p->data[p->cursor], uin, hour, minute, day, month, year);
+        icq_UDPAck(link, seq);
+        break;
+      case UDP_SRV_X1: /* unknown message sent after login*/
+        icq_FmtLog(link, ICQ_LOG_MESSAGE, "Acknowleged UDP_SRV_X1 (Begin messages)\n");
+        icq_UDPAck(link, seq);
+        break;
+      case UDP_SRV_X2: /* unknown message sent after login*/
+        icq_FmtLog(link, ICQ_LOG_MESSAGE, "Acknowleged UDP_SRV_X2 (Done old messages)\n");
+        icq_UDPAck(link, seq);
+        icq_SendGotMessages(link);
+        break;
+      case UDP_SRV_INFO_REPLY:
+        icq_HandleInfoReply(link, p);
+        break;
+      case UDP_SRV_EXT_INFO_REPLY:
+        icq_HandleExtInfoReply(link, p);
+        break;
+      case UDP_SRV_USER_ONLINE:
+        icq_HandleUserOnline(link, p);
+        break;
+      case UDP_SRV_USER_OFFLINE:
+        icq_HandleUserOffline(link, p);
+        break;
+      case UDP_SRV_TRY_AGAIN:
+        icq_FmtLog(link, ICQ_LOG_WARNING, "Server is busy, please try again\n");
+        icq_Login(link, link->icq_Status);
+        break;
+      case UDP_SRV_STATUS_UPDATE:
+        icq_HandleStatusChange(link, p);
+        break;
+      case UDP_SRV_GO_AWAY:
+        icq_FmtLog(link, ICQ_LOG_ERROR, "Server has forced us to disconnect\n");
+        if(link->icq_Disconnected)
+          (*link->icq_Disconnected)(link);
+        break;
+      case UDP_SRV_END_OF_SEARCH:
+        icq_FmtLog(link, ICQ_LOG_MESSAGE, "Search done\n");
+        if(link->icq_SearchDone)
+          (*link->icq_SearchDone)(link);
+        icq_UDPAck(link, seq);
+        break;
+      case UDP_SRV_USER_FOUND:
+        icq_HandleSearchReply(link, p);
+        break;
+      case UDP_SRV_ONLINE_MESSAGE: /* Online message through the server */
+        cur_time = time(0L);
+        tm_str = localtime(&cur_time);
+        icq_PacketGotoUDPInData(p, 0);
+        uin = icq_PacketRead32(p);
+        type = icq_PacketRead16(p);
+        len = icq_PacketRead16(p);
+        icq_DoMsg(link, type, len, (char*)&p->data[p->cursor], uin, tm_str->tm_hour,
+                  tm_str->tm_min, tm_str->tm_mday, tm_str->tm_mon+1, tm_str->tm_year+1900);
+        icq_UDPAck(link, seq);
+        break;
+      case UDP_SRV_WRONG_PASSWORD:
+        icq_FmtLog(link, ICQ_LOG_ERROR, "Wrong password\n");
+        if(link->icq_WrongPassword)
+          (*link->icq_WrongPassword)(link);
+        icq_UDPAck(link, seq);
+        break;
+      case UDP_SRV_INVALID_UIN:
+        icq_FmtLog(link, ICQ_LOG_WARNING, "Invalid UIN\n");
+        if(link->icq_InvalidUIN)
+          (*link->icq_InvalidUIN)(link);
+        icq_UDPAck(link, seq);
+        break;
+      case UDP_SRV_META_USER:
+        icq_HandleMetaUserInfo(link, p);
+        break;
+      default: /* commands we dont handle yet */
+        icq_FmtLog(link, ICQ_LOG_WARNING, "Unhandled 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 */
+        break;
+    }
+  }
+  else
+  {
+    icq_FmtLog(link, ICQ_LOG_WARNING, "Unhandled 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 */
+  }
+}
+
+/******************************************
+Handles packets that the server sends to us.
+*******************************************/
+void icq_HandleServerResponse(ICQLINK *link)
+{
+  WORD seq, cmd;
+  int s;
+  icq_Packet *p;
+
+  p = icq_PacketNew();
+  s = icq_UDPSockRead(link, p);
+  p->length = s;
+  if(s<=0)
+  {
+    icq_FmtLog(link, ICQ_LOG_FATAL, "Connection terminated\n");
+    icq_Disconnect(link);
+    if(link->icq_Disconnected)
+      (*link->icq_Disconnected)(link);
+  }
+  seq = icq_PacketReadUDPInSeq1(p);
+  cmd = icq_PacketReadUDPInCmd(p);
+  if(icq_GetServMess(link, seq) && cmd != UDP_SRV_NEW_UIN && cmd != UDP_SRV_GO_AWAY && cmd != UDP_SRV_ACK)
+  {
+    icq_FmtLog(link, ICQ_LOG_WARNING, "Ignored a message cmd %04x, seq %04x\n", cmd, seq);
+    icq_UDPAck(link, seq); /* LAGGGGG!! */
+    icq_PacketDelete(p);
+    return;
+  }
+  if(cmd != UDP_SRV_ACK)
+    icq_SetServMess(link, seq);
+
+  icq_ServerResponse(link, p);
+
+  icq_PacketDelete(p);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/util.c	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,541 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+$Id: util.c 1162 2000-11-28 02:22:42Z warmenhoven $
+$Log$
+Revision 1.1  2000/11/28 02:22:42  warmenhoven
+icq. whoop de doo
+
+Revision 1.32  2000/07/22 16:49:32  denis
+Trinidad and Tobago country was added.
+
+Revision 1.31  2000/07/21 16:51:20  denis
+All languages, possible in original icq were added.
+Occupation array fixed.
+
+Revision 1.30  2000/07/20 09:58:59  denis
+Occupation table corrected to comply with original ICQ.
+
+Revision 1.29  2000/07/04 07:25:29  pcadach
+icq_FmtLog() crashed when it receives NULL at link argument.
+
+Revision 1.28  2000/06/30 13:59:43  denis
+Slovak Republic country code fixed.
+
+Revision 1.27  2000/06/25 17:00:32  denis
+icq_MetaOccupation[], icq_MetaPastBackgrounds[],
+icq_MetaAffiliations[] and icq_MetaLanguages[] arrays were added along
+with icq_GetMetaOccupationName(), icq_GetMetaBackgroundName(),
+icq_GetMetaAffiliationName() and icq_GetMetaLanguageName() functions
+to access them.
+
+Revision 1.26  2000/05/21 17:42:51  denis
+Bulgaria country code was added. Thanks to
+"Napalm Death" <napalmbox@hotmail.com>
+
+Revision 1.25  2000/05/03 18:29:15  denis
+Callbacks have been moved to the ICQLINK structure.
+
+Revision 1.24  2000/04/10 16:36:04  denis
+Some more Win32 compatibility from Guillaume Rosanis <grs@mail.com>
+
+Revision 1.23  2000/04/05 14:37:02  denis
+Applied patch from "Guillaume R." <grs@mail.com> for basic Win32
+compatibility.
+
+Revision 1.22  2000/03/31 12:49:15  nofate
+remove static variable
+
+Revision 1.21  1999/11/11 15:10:33  guruz
+- Added Base for Webpager Messages. Please type "make fixme"
+- Removed Segfault when kicq is started the first time
+
+Revision 1.20  1999/10/07 18:01:40  denis
+Cleanups.
+
+Revision 1.19  1999/09/29 17:16:45  denis
+Cleanups.
+
+Revision 1.18  1999/07/18 20:24:27  bills
+removed old byte order and contact list functions
+
+Revision 1.17  1999/07/16 15:46:03  denis
+Cleaned up.
+
+Revision 1.16  1999/07/16 12:04:49  denis
+Status support changed.
+
+Revision 1.15  1999/07/12 15:13:46  cproch
+- added definition of ICQLINK to hold session-specific global variabled
+  applications which have more than one connection are now possible
+- changed nearly every function defintion to support ICQLINK parameter
+
+Revision 1.14  1999/04/17 19:20:35  bills
+removed *_link entries from icq_ContactItem, including cleanup/init code
+
+Revision 1.13  1999/04/14 15:06:51  denis
+Cleanups for "strict" compiling (-ansi -pedantic)
+
+*/
+
+#include <stdlib.h>
+#include <ctype.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#include "icqtypes.h"
+#include "icq.h"
+#include "icqlib.h"
+#include "stdpackets.h"
+#include "util.h"
+#include "stdarg.h"
+
+/*
+ * This list of countries should be sorted according to country code.
+ * When adding new country, please preserve the order!
+ */
+icq_ArrayType icq_Countries[] = {
+  {"USA",1},
+  {"Russia",7},
+  {"Egypt",20},
+  {"South Africa",27},
+  {"Greece",30},
+  {"Netherlands",31},
+  {"Belgium",32},
+  {"France",33},
+  {"Monaco",33},
+  {"Spain",34},
+  {"Hungary",36},
+  {"Yugoslavia",38},
+  {"Italy",39},
+  {"San Marino",39},
+  {"Vatican City",39},
+  {"Romania",40},
+  {"Liechtenstein",41},
+  {"Switzerland",41},
+  {"Czech Republic",42},
+  {"Austria",43},
+  {"UK",44},
+  {"Denmark",45},
+  {"Sweden",46},
+  {"Norway",47},
+  {"Poland",48},
+  {"Germany",49},
+  {"Peru",51},
+  {"Mexico",52},
+  {"Guantanomo Bay",53},
+  {"Argentina",54},
+  {"Brazil",55},
+  {"Chile",56},
+  {"Columbia",57},
+  {"Venezuela",58},
+  {"Malaysia",60},
+  {"Australia",61},
+  {"Indonesia",62},
+  {"Philippines",63},
+  {"New Zealand",64},
+  {"Singapore",65},
+  {"Thailand",66},
+  {"Japan",81},
+  {"South Korea",82},
+  {"Vietnam",84},
+  {"China",86},
+  {"Turkey",90},
+  {"India",91},
+  {"Pakistan",92},
+  {"Sri Lanka",94},
+  {"Iran",98},
+  {"Canada",107},
+  {"Morocco",212},
+  {"Algeria",213},
+  {"Tunisia",216},
+  {"Libya",218},
+  {"Senegal",221},
+  {"Mali",223},
+  {"Ivory Coast",225},
+  {"Liberia",231},
+  {"Ghana",233},
+  {"Nigeria",234},
+  {"Cameroon",237},
+  {"Gabon",241},
+  {"Zaire",243},
+  {"Ethiopia",251},
+  {"Kenya",254},
+  {"Tanzania",255},
+  {"Zimbabwe",263},
+  {"Namibia",264},
+  {"Malawi",265},
+  {"Aruba",297},
+  {"Portugal",351},
+  {"Luxembourg",352},
+  {"Ireland",353},
+  {"Iceland",354},
+  {"Malta",356},
+  {"Cyprus",357},
+  {"Finland",358},
+  {"Bulgaria",359},
+  {"Ukraine",380},
+  {"Belize",501},
+  {"Guatemala",502},
+  {"El Salvador",503},
+  {"Honduras",504},
+  {"Nicaragua",505},
+  {"Costa Rice",506},
+  {"Panama",507},
+  {"Haiti",509},
+  {"Guadeloupe",590},
+  {"Bolivia",591},
+  {"Guyana",592},
+  {"Ecuador",593},
+  {"Paraguay",595},
+  {"French Antilles",596},
+  {"Suriname",597},
+  {"Uruguay",598},
+  {"Netherlands Antilles",599},
+  {"Saipan",670},
+  {"Saipan",670},
+  {"Guam",671},
+  {"Papua New Guinea",675},
+  {"Fiji",679},
+  {"American Samoa",684},
+  {"New Caledonia",687},
+  {"French Polynesia",689},
+  {"Hong Kong",852},
+  {"Trinidad and Tobago",868},
+  {"Bangladesh",880},
+  {"Taiwan",886},
+  {"Jordan",962},
+  {"Iraq",964},
+  {"Kuwait",965},
+  {"Saudia Arabia",966},
+  {"Yemen",967},
+  {"Oman",968},
+  {"United Arab Emirates",971},
+  {"Israel",972},
+  {"Bahrain",973},
+  {"Qatar",974},
+  {"Nepal",977},
+  {"Slovak Republic",4201},
+  {"Not entered",0xffff},
+};
+
+icq_ArrayType icq_MetaOccupation[] = {
+  {"Academic", 1},
+  {"Administrative", 2},
+  {"Art/Entertainment", 3},
+  {"College Student", 4},
+  {"Computers", 5},
+  {"Community & Social", 6},
+  {"Education", 7},
+  {"Engineering", 8},
+  {"Financial Services", 9},
+  {"Government", 10},
+  {"High School Student", 11},
+  {"Home", 12},
+  {"ICQ - Providing Help", 13},
+  {"Law", 14},
+  {"Managerial", 15},
+  {"Manufacturing", 16},
+  {"Medical/Health", 17},
+  {"Military", 18},
+  {"Non-Government Organization", 19},
+  {"Professional", 20},
+  {"Retail", 21},
+  {"Retired", 22},
+  {"Science & Research", 23},
+  {"Sports", 24},
+  {"Technical", 25},
+  {"University Student", 26},
+  {"Web Building", 27},
+  {"Other Services", 99},
+};
+
+icq_ArrayType icq_MetaPastBackgrounds[] = {
+  {"Elementary School", 300},
+  {"High School", 301},
+  {"College", 302},
+  {"University", 303},
+  {"Military", 304},
+  {"Past Work Place", 305},
+  {"Past Organization", 306},
+  {"Other", 399},
+};
+
+icq_ArrayType icq_MetaAffiliations[] = {
+  {"Alumni Org.", 200},
+  {"Charity Org.", 201},
+  {"Club/Social Org.", 202},
+  {"Community Org.", 203},
+  {"Cultural Org.", 204},
+  {"Fan Clubs", 205},
+  {"Fraternity/Sorority", 206},
+  {"Hobbyists Org.", 207},
+  {"International Org.", 208},
+  {"Nature and Environment Org.", 209},
+  {"Professional Org.", 210},
+  {"Scientific/Technical Org.", 211},
+  {"Self Improvement Group", 212},
+  {"Spiritual/Religious Org.", 213},
+  {"Sports Org.", 214},
+  {"Support Org.", 215},
+  {"Trade and Business Org.", 216},
+  {"Union", 217},
+  {"Voluntary Org.", 218},
+  {"Other", 299},
+};
+
+icq_ArrayType icq_MetaLanguages[] = {
+  {"Not Entered", 0},
+  {"Arabic", 1},
+  {"Bhojpuri", 2},
+  {"Bulgarian", 3},
+  {"Burmese", 4},
+  {"Cantonese", 5},
+  {"Catalan", 6},
+  {"Chinese", 7},
+  {"Croatian", 8},
+  {"Czech", 9},
+  {"Danish", 10},
+  {"Dutch", 11},
+  {"English", 12},
+  {"Esperanto", 13},
+  {"Estonian", 14},
+  {"Farsi", 15},
+  {"Finnish", 16},
+  {"French", 17},
+  {"Gaelic", 18},
+  {"German", 19},
+  {"Greek", 20},
+  {"Hebrew", 21},
+  {"Hindi", 22},
+  {"Hungarian", 23},
+  {"Icelandic", 24},
+  {"Indonesian", 25},
+  {"Italian", 26},
+  {"Japanese", 27},
+  {"Khmer", 28},
+  {"Korean", 29},
+  {"Lao", 30},
+  {"Latvian", 31},
+  {"Lithuanian", 32},
+  {"Malay", 33},
+  {"Norwegian", 34},
+  {"Polish", 35},
+  {"Portuguese", 36},
+  {"Romanian", 37},
+  {"Russian", 38},
+  {"Serbian", 39},
+  {"Slovak", 40},
+  {"Slovenian", 41},
+  {"Somali", 42},
+  {"Spanish", 43},
+  {"Swahili", 44},
+  {"Swedish", 45},
+  {"Tagalog", 46},
+  {"Tatar", 47},
+  {"Thai", 48},
+  {"Turkish", 49},
+  {"Ukrainian", 50},
+  {"Urdu", 51},
+  {"Vietnamese", 52},
+  {"Yiddish", 53},
+  {"Yoruba", 54},
+  {"Afrikaans", 55},
+  {"Bosnian", 56},
+  {"Persian", 57},
+  {"Albanian", 58},
+  {"Armenian", 59},
+  {"Punjabi", 60},
+  {"Chamorro", 61},
+  {"Mongolian", 62},
+  {"Mandarin", 63},
+  {"Taiwaness", 64},
+  {"Macedonian", 65},
+  {"Sindhi", 66},
+  {"Welsh", 67},
+};
+
+void hex_dump(char *data, long size)
+{
+  long i;
+  long x;
+  int r=1;
+  char d[32];
+  unsigned char bfr[64];
+  for(i=0, x=0;;i++)
+  {
+    if(i<size)
+    {
+      if(x==0)
+        printf("%04lx: ", i);
+#ifdef _WIN32
+      sprintf(d, "%08x", data[i]);
+#else
+      snprintf(d, 9, "%08x", data[i]);
+#endif
+      printf("%c%c ", d[6], d[7]);
+      bfr[x]=data[i];
+      if(bfr[x]<0x20)
+        bfr[x]='.';
+      if(bfr[x]>0x7f)
+        bfr[x]='.';
+    }
+    else
+    {
+      if(x==0)
+        break;
+      else
+      {
+        printf("   ");
+        bfr[x]=' ';
+        r=0;
+      }
+    }
+    x++;
+    if(!(x<16))
+    {
+      bfr[x]=0;
+      printf("%s\n", bfr);
+      x=0;
+      if(!r)
+        break;
+    }
+  }
+}
+
+/* simple mapping for udp status->tcp status translation function */
+struct icq_TCPStatusRec
+{
+    unsigned long udp_status;
+    long tcp_status;
+} icq_TCPStatusMap[] = {
+    { STATUS_OFFLINE     , 0                        }, 
+    { STATUS_ONLINE      , ICQ_TCP_STATUS_ONLINE    }, 
+    { STATUS_INVISIBLE   , ICQ_TCP_STATUS_INVISIBLE },
+    { STATUS_NA          , ICQ_TCP_STATUS_NA        },
+    { STATUS_FREE_CHAT   , ICQ_TCP_STATUS_FREE_CHAT },
+    { STATUS_OCCUPIED    , ICQ_TCP_STATUS_OCCUPIED  },
+    { STATUS_AWAY        , ICQ_TCP_STATUS_AWAY      },
+    { STATUS_DND         , ICQ_TCP_STATUS_DND       },
+};
+
+long icq_TCPXlateStatus(unsigned long udp_status)
+{
+  unsigned int i;
+  for(i=0;i<sizeof(icq_TCPStatusMap)/sizeof(struct icq_TCPStatusRec);i++)
+    if(icq_TCPStatusMap[i].udp_status==udp_status) 
+      return icq_TCPStatusMap[i].tcp_status;
+  /* warning: "couldn't find tcp status for %d, assuming 0", udp_status */
+  return 0;
+}
+
+void icq_FmtLog(ICQLINK *link, int level, const char *fmt, ...)
+{
+  char buffer[2048];
+  va_list ap;
+  va_start(ap, fmt);
+  
+  if(!link)
+    return;
+#ifdef _MSVC_
+  _vsnprintf(buffer, 1024, fmt, ap);
+#else
+  (void)vsnprintf(buffer, 1024, fmt, ap);
+#endif
+  va_end(ap);
+
+  if(link->icq_Log && icq_LogLevel>=level)
+    (*link->icq_Log)(link, time(0L), level, buffer);
+}
+
+/**
+ * Following functions used by qsort and bsearch to
+ * compare 2 pointers to icq_ArrayType object.
+ */
+int array_code_compare(const void *x, const void *y)
+{
+  return ((icq_ArrayType*)x)->code - ((icq_ArrayType*)y)->code;
+}
+
+const char *icq_GetCountryName(unsigned short code)
+{
+  icq_ArrayType *res,key;
+    
+  key.code=code;
+  res=bsearch(&key, icq_Countries, sizeof(icq_Countries)/sizeof(icq_ArrayType),
+              sizeof(icq_ArrayType), array_code_compare);
+    
+  return res?res->name:"Unknown";
+}
+
+const char *icq_GetMetaOccupationName(unsigned short code)
+{
+  icq_ArrayType *res,key;
+    
+  key.code=code;
+  res=bsearch(&key, icq_MetaOccupation, sizeof(icq_MetaOccupation)/sizeof(icq_ArrayType),
+              sizeof(icq_ArrayType), array_code_compare);
+    
+  return res?res->name:"Unknown";
+}
+
+const char *icq_GetMetaBackgroundName(unsigned short code)
+{
+  icq_ArrayType *res,key;
+    
+  key.code=code;
+  res=bsearch(&key, icq_MetaPastBackgrounds, sizeof(icq_MetaPastBackgrounds)/sizeof(icq_ArrayType),
+              sizeof(icq_ArrayType), array_code_compare);
+    
+  return res?res->name:"Unknown";
+}
+
+const char *icq_GetMetaAffiliationName(unsigned short code)
+{
+  icq_ArrayType *res,key;
+    
+  key.code=code;
+  res=bsearch(&key, icq_MetaAffiliations, sizeof(icq_MetaAffiliations)/sizeof(icq_ArrayType),
+              sizeof(icq_ArrayType), array_code_compare);
+    
+  return res?res->name:"Unknown";
+}
+
+const char *icq_GetMetaLanguageName(unsigned short code)
+{
+  icq_ArrayType *res,key;
+    
+  key.code=code;
+  res=bsearch(&key, icq_MetaLanguages, sizeof(icq_MetaLanguages)/sizeof(icq_ArrayType),
+              sizeof(icq_ArrayType), array_code_compare);
+    
+  return res?res->name:"Unknown";
+}
+
+/********************************************
+returns a string describing the status or
+a "Error" if no such string exists
+*********************************************/
+const char *icq_ConvertStatus2Str(unsigned long status)
+{
+  if((unsigned long)STATUS_OFFLINE == status) /* this because -1 & 0x01FF is not -1 */
+    return "Offline";
+
+  if((status & STATUS_INVISIBLE) == STATUS_INVISIBLE)
+    return "Invisible";
+  else if((status & STATUS_FREE_CHAT) == STATUS_FREE_CHAT)
+    return "Free for chat";
+  else if((status & STATUS_DND) == STATUS_DND)
+    return "Do not disturb";
+  else if((status & STATUS_OCCUPIED) == STATUS_OCCUPIED)
+    return "Occupied";
+  else if((status & STATUS_NA) == STATUS_NA)
+    return "Not available";
+  else if((status & STATUS_AWAY) == STATUS_AWAY)
+    return "Away";
+  else if(!(status & 0x01FF))
+    return "Online";
+  else
+    return "Error";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/icq/util.h	Tue Nov 28 02:22:42 2000 +0000
@@ -0,0 +1,37 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+#ifndef _UTIL_H_
+#define _UTIL_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#ifdef _WIN32
+#include <winsock.h>
+#else
+#include <netinet/in.h>
+#endif
+
+#include "icqtypes.h"
+#include "icq.h"
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE !FALSE
+#endif
+
+void hex_dump(char *data, long size);
+
+WORD Chars_2_Word(unsigned char *buf);
+DWORD Chars_2_DW(unsigned char *buf);
+void DW_2_Chars(unsigned char *buf, DWORD num);
+void Word_2_Chars(unsigned char *buf, WORD num);
+
+const char *icq_ConvertStatus2Str(unsigned long status);
+
+#endif /* _UTIL_H_ */
--- a/src/util.c	Tue Nov 28 00:53:27 2000 +0000
+++ b/src/util.c	Tue Nov 28 02:22:42 2000 +0000
@@ -828,7 +828,7 @@
 	return button;
 }
 
-static GtkTooltips *tips = NULL;
+static GtkTooltips *button_tips = NULL;
 GtkWidget *picture_button2(GtkWidget *window, char *text, char **xpm, short dispstyle)
 {
 	GtkWidget *button;
@@ -838,7 +838,7 @@
 	GtkWidget *pixmap;
 	GtkWidget *label;
 	
-	if (!tips) tips = gtk_tooltips_new();
+	if (!button_tips) button_tips = gtk_tooltips_new();
 	button = gtk_button_new();
 	if (display_options & OPT_DISP_COOL_LOOK)
 		gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
@@ -869,7 +869,7 @@
 		gtk_box_pack_end(GTK_BOX(button_box_2), label, FALSE, FALSE, 0);
 	}
 
-	gtk_tooltips_set_tip(tips, button, text, "Gaim");	
+	gtk_tooltips_set_tip(button_tips, button, text, "Gaim");	
 	gtk_widget_show(button);
 	return button;
 }