changeset 1054:0b0b4cb53c17

[gaim-migrate @ 1064] yahoo prpl committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Fri, 03 Nov 2000 10:03:53 +0000
parents 864f4aae0b60
children 5a99def38a47
files configure.in plugins/Makefile.am plugins/yay/.cvsignore plugins/yay/AUTHORS plugins/yay/COPYING plugins/yay/ChangeLog plugins/yay/INSTALL plugins/yay/Makefile.am plugins/yay/NEWS plugins/yay/NOTES plugins/yay/README plugins/yay/libyahoo-proto.h plugins/yay/libyahoo.c plugins/yay/libyahoo.h plugins/yay/memtok.c plugins/yay/memtok.h plugins/yay/yay.c
diffstat 16 files changed, 5150 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/configure.in	Fri Nov 03 01:33:28 2000 +0000
+++ b/configure.in	Fri Nov 03 10:03:53 2000 +0000
@@ -197,6 +197,7 @@
 	   intl/Makefile
            sounds/Makefile
 	   plugins/Makefile
+	   plugins/yay/Makefile
            pixmaps/Makefile
            libfaim/Makefile
 	   po/Makefile.in
--- a/plugins/Makefile.am	Fri Nov 03 01:33:28 2000 +0000
+++ b/plugins/Makefile.am	Fri Nov 03 10:03:53 2000 +0000
@@ -4,7 +4,10 @@
 	$(CC) $(CFLAGS) -I../src -DVERSION=\"$(VERSION)\" -o $@ $< $(LDFLAGS) $(PLUGIN_LIBS)
 
 if PLUGINS
-plugin_DATA = autorecon.so iconaway.so notify.so spellchk.so lagmeter.so
+
+SUBDIRS = yay
+
+plugin_DATA = autorecon.so iconaway.so irc.so notify.so spellchk.so lagmeter.so
 plugindir = $(libdir)/gaim
 
 clean distclean:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/yay/.cvsignore	Fri Nov 03 10:03:53 2000 +0000
@@ -0,0 +1,8 @@
+Makefile
+Makefile.in
+.deps
+.libs
+libyahoo.lo
+memtok.lo
+yay.lo
+libyahoo.la
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/yay/AUTHORS	Fri Nov 03 10:03:53 2000 +0000
@@ -0,0 +1,50 @@
+Primary Authors
+---------------
+Nathan Neulinger    <nneul@umr.edu>
+	http://www.umr.edu/~nneul/
+	GTK interface and rewrite of protocol handling code
+
+Supporting Authors
+------------------
+Jay Lubomirski <jaylubo@fiam.net>
+	Work on conferencing support
+Gary Godfrey <Gary.Godfrey@amd.com>
+	Misc. patches to config and cookie parsing
+Scott D. Heavner <sdh@po.cwru.edu>
+	Support for actions, window creation/sizing improvements, etc.
+Scott A. Barron <kain224@yahoo.com>
+	Lots of patches to clean up user interface, using tables, etc.
+	Support for clicking on mail status icon to open web browser.
+Thomas James <tbjames@bellsouth.net>
+	Patched version of gtkyahoo that had initial http mode support
+Roberto Machorro Angoa <rmach@bigfoot.com>
+	http://www.bigfoot.com/~rmach/
+	Misc. suggestions, screenshots, GTK coding assistance
+	Sample icon code and gtkyahoo icon
+Craig Emery <ranec@yahoo.com>
+	Info on calendar and new mail protocol packets
+	AIX and other misc. patches
+	Lots of additional functionality
+Douglas Winslow <douglas@min.net>
+	Prototype code for Yahoo Pager protocol
+Jon Keating <jonkeating@norcom2000.com>
+	Patch for password validation checking
+Nicolas Barry <boozai@yahoo.com>
+	Couple of buffer overrun patches
+Keeyeong Tan <encloaking_darkness@yahoo.com>
+	Custom status window
+
+Acknowledgements
+----------------
+Andreas Plesner Jacobsen <scoof@nerd.dk>
+	Debian package maintainer
+Kurt Granroth <granroth@kde.org> 
+	Grabbed his icons from KBiff for the mail indicator
+Mary Hart-Byfield <kimbykitten@yahoo.com>
+	Windows pager interoperability testing
+Timothy Allen <inkumbi@yahoo.com>
+	Helped diagnose problem with non-encoded userid and password in request
+	for login cookie. Also problem with no newline on last line of
+	config file. Numerous xpm suggestions and examples.
+Dan Nguyen <nguyend7@cse.msu.edu>
+	Debian build fixes
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/yay/COPYING	Fri Nov 03 10:03:53 2000 +0000
@@ -0,0 +1,402 @@
+
+
+		    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.
+
+
+The following copyright notice applies to the SHA1
+implementation:
+
+
+ Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ All rights reserved.
+
+ This package is an SSL implementation written
+ by Eric Young (eay@cryptsoft.com).
+ The implementation was written so as to conform with Netscapes SSL.
+ 
+ This library is free for commercial and non-commercial use as long as
+ the following conditions are aheared to.  The following conditions
+ apply to all code found in this distribution, be it the RC4, RSA,
+ lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ included with this distribution is covered by the same copyright terms
+ except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ 
+ Copyright remains Eric Young's, and as such any Copyright notices in
+ the code are not to be removed.
+ If this package is used in a product, Eric Young should be given attribution
+ as the author of the parts of the library used.
+ This can be in the form of a textual message at program startup or
+ in documentation (online or textual) provided with the package.
+ 
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+    must display the following acknowledgement:
+    "This product includes cryptographic software written by
+     Eric Young (eay@cryptsoft.com)"
+    The word 'cryptographic' can be left out if the rouines from the library
+    being used are not cryptographic related :-).
+ 4. If you include any Windows specific code (or a derivative thereof) from 
+    the apps directory (application code) you must include an acknowledgement:
+    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ 
+ THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+ 
+ The licence and distribution terms for any publically available version or
+ derivative of this code cannot be changed.  i.e. this code cannot simply be
+ copied and put under another distribution licence
+ [including the GNU Public Licence.]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/yay/ChangeLog	Fri Nov 03 10:03:53 2000 +0000
@@ -0,0 +1,18 @@
+libyahoo 0.17:
+	Initial introduction, corresponds to development version
+		of gtkyahoo.
+	Added some NULL pointer checks to yahoo_array2list and yahoo_cmd_decline_conf
+	Added new memtok utility function (see memtok.c) and used it in some of the
+		conference packet parsing routines
+	Small #include changes for building under Solaris
+	Added NOTES file as small beginnings of documentation process
+	Cleaned up compiler warnings when building under Solaris
+	Started adding support for getting address book entries of Yahoo! buddies
+		Currently they're successfully retrieved but not kept anywhere useful
+	All addresses can now be retrieved into a context as follows:
+		struct yahoo_address   = structure with name, phone numbers...
+		context->address_count = number of addresses
+		context->addresses     = pointer to first address
+		I currently DO NOT call yahoo_fetchaddresses from within yahoo_init, I think it should be optional
+		See yahoo_free_addresses for how to iterate over addresses
+	Added patch for removebuddy + http proxy support
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/yay/INSTALL	Fri Nov 03 10:03:53 2000 +0000
@@ -0,0 +1,76 @@
+Simple install procedure
+========================
+
+  % gzip -cd gtkyahoo-<version>.tar.gz | tar xvf - # unpack the sources
+  % cd gtkyahoo-<version>               # change to the toplevel directory
+  % ./configure                         # run the `configure' script
+  % make                                # build GTKYahoo
+  [ Become root if necessary ]
+  % make install                        # install GTKYahoo
+  % gtkyahoo                            # run gtkyahoo once
+  % vi $HOME/.gtkyahoo/gtkyahoorc       # update/create config file
+
+NOTE - OpenBSD (and possibly other *BSD) users might need to use gmake
+instead of make when compiling this software.
+
+The Nitty-Gritty
+================
+
+The 'configure' script can be given a number of options to enable
+and disable various features. For a complete list, type:
+
+  ./configure --help
+
+A few of the more important ones:
+
+*  --prefix=PREFIX         install architecture-independent files in PREFIX
+                           [ Defaults to /usr/local ]
+
+Options can be given to the compiler and linker by setting
+environment variables before running configure. A few of the more
+important ones:
+
+ CC       : The C compiler to use
+ CPPFLAGS : Flags for the C preprocesser such as -I and -D
+ CFLAGS   : C compiler flags
+
+The most important use of this is to set the
+optimization/debugging flags. For instance, to compile with no
+debugging information at all, run configure as:
+
+ CFLAGS=-O2 ./configure           # Bourne compatible shells (sh/bash/zsh)
+
+or,
+
+ setenv CFLAGS -O2 ; ./configure  # csh and variants
+
+
+Installation directories
+========================
+
+The location of the installed files is determined by the --prefix
+and --exec-prefix options given to configure. There are also more
+detailed flags to control individual directories. However, the
+use of these flags is not tested.
+
+
+BSD build instructions
+======================
+
+BSD users might need to use gmake instead of make when compiling this
+software.
+
+
+Debian build instructions
+=========================
+
+Requires fakeroot and debhelper packages installed.
+
+% fakeroot
+% debian/rules binary
+
+This will create a gtkyahoo-<version>.deb file in the higher
+directory, not <version> stands for the version number.
+
+[become root]
+% dpkg -i gtkyahoo-<version>.deb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/yay/Makefile.am	Fri Nov 03 10:03:53 2000 +0000
@@ -0,0 +1,10 @@
+CFLAGS = -g -O2 -I../../src -I../../libfaim/faim -I../../libfaim $(GTK_CFLAGS)
+LIBS = $(GTK_LIBS)
+
+pkgdir = $(libdir)/gaim
+pkg_LTLIBRARIES = libyahoo.la
+
+libyahoo_la_SOURCES = libyahoo.c memtok.c yay.c
+
+EXTRA_DIST = libyahoo-proto.h libyahoo.h memtok.h \
+		AUTHORS COPYING ChangeLog INSTALL NEWS NOTES README
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/yay/NOTES	Fri Nov 03 10:03:53 2000 +0000
@@ -0,0 +1,61 @@
+Small scenario notes by Craig:
+
+Here's the scenario:
+
+The pager does the normal cookie retrieval thing with
+http://msg.edit.yahoo.com:80/config/ncclogin?.src=bl&login=<USERID>&passwd=<PASSWORD>0&n=1&t=1
+
+which gives you the cookies
+(Y=n=<NSUBCOOKIE>&l=<LSUBCOOKIE> is all you need to keep).
+
+( I was thinking that we might include a configurable option to "put" this into Netscape's cookies file
+just like the Win32 version does. )
+
+Then:
+
+http://msg.edit.yahoo.com:80/config/get_buddylist?.src=bl&.l=<USERID>
+
+if given the cookies
+Y=v=1&n=<NSUBCOOKIE>&l=<LSUBCOOKIE> (where <NSUBCOOKIE> and <LSUBCOOKIE> were retrieved from ncclogin)
+gives you the buddies list as:
+
+BEGIN BUDDYLIST
+<GROUP>:ID[,IDn]*
+END BUDDYLIST
+BEGIN IGNORELIST
+
+END IGNORELIST
+BEGIN IDENTITIES
+<PRIMARYID>[,<OTHERID>]*
+END IDENTITIES
+Mail=<UNREADMAIL>
+Login=<PRIMARYID>
+
+You can get details of the people in your Yahoo!  Address book for which you have mentioned their Messenger ID with:
+
+http://uk.address.yahoo.com:80/yab/uk/yab?v=PG&A=s
+with cookies Y=v=1&n=<NSUBCOOKIE>&l=<LSUBCOOKIE>
+gives:
+
+1^I
+<ID>:<FIRSTNAME>^I<LASTNAME>^I<EMAILNICKNAME>^I<EMAIL>^I<HOMEPHONE>^I<WORKPHONE>^I[01]^I<ENTRYID>
+
+(the [01] is 0 if the entry's Primary phone is "Home"
+and 1 if it's "Work")
+
+so for me it **might** be:
+
+ranec:Craig^IEmery^Iranec@yahoo.com^I+44 UK work^I+44 UK home^I1^I123
+
+( I **really** want to get these entries retreived by libyahoo so I can use them as tool-tips on your friend's id's just like the
+Win32 version does. )
+
+Anyway after loging in and getting the buddies list and your address book entries, it periodically opens a connection to:
+
+http://http.pager.yahoo.com:80/notify/
+
+and I don't know the details of this traffic 'cause I've got no packet sniffing on Win23 (NT actually).
+
+Has anyone else out there traced any of the "notify" traffic?
+
+All I need is this and I can get GtkYahoo working entirely over HTTP (even HTTP proxies) and firewalls become irrelevant!
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/yay/README	Fri Nov 03 10:03:53 2000 +0000
@@ -0,0 +1,59 @@
+Introduction:
+-------------
+This is GTKYahoo, a GPL'd GTK Yahoo! Pager client. It is functional
+enough to carry on normal conversations. New features, and additional
+functionality is being added quite frequently.
+
+Please send me patches/fixes/additions/suggestions... Any help is
+appreciated.
+
+I _HIGHLY_ suggest reading the ChangeLog and other files in here to get
+some details on what is going on with the program, etc.
+
+This software is not supported or sponsored in any way by Yahoo!. 
+
+Where to get:
+-------------
+Home Page: http://www.unixtools.org/gtkyahoo/
+Download Area: http://www.unixtools.org/gtkyahoo/dist/
+Anon-CVS: 
+	Root: :pserver:cvs@cvs.unixtools.org:/cvsroot-gtkyahoo
+	Password: cvs
+	Module: gtkyahoo
+
+Usage notes:
+------------
+The first time you run GTKYahoo it will create a configuration directory
+and config file. Edit it prior to running the program again.
+
+Look at the sample gtkyahoorc file for info on other options. Note, many
+of the features are unimplemented at the moment.
+
+Debugging options are available in the config file, syntax is:
+	
+	debug "keyword" level
+
+i.e.
+	
+	debug "yahoolib" 1
+
+Available keywords include: 
+	packets: enables tracing of received packets
+	yahoolib: enables debugging of yahoolib actions
+	sendraw: enables the sendraw facility
+
+Development notes:
+------------------
+This program makes use of the cfunctions program to build some of it's
+header files. This is only done in response to issuing "make proto".
+The cfunctions tool is available from the URL:
+
+	http://www.hayamasa.demon.co.uk/cfunctions
+
+The yahoolib files can be pulled out and used to implement the pager
+protocol. They are not documented however. The basic functionality of the library is that you give it a pointer to a buffer area, and the size of the buffer, 
+and it will return you a raw packet if the buffer contains one. The actual
+I/O with the server is up to you.
+
+Other suggested packages include:
+	bison, flex, ElectricFence, cvs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/yay/libyahoo-proto.h	Fri Nov 03 10:03:53 2000 +0000
@@ -0,0 +1,104 @@
+/* This is a Cfunctions (version 0.24) generated header file.
+   Cfunctions is a free program for extracting headers from C files.
+   Get Cfunctions from `http://www.hayamasa.demon.co.uk/cfunctions'. */
+
+/* This file was generated with:
+`cfunctions -w LIBYAHOO_PROTO -o ./libyahoo-proto.h' */
+#ifndef CFH_LIBYAHOO_PROTO
+#define CFH_LIBYAHOO_PROTO
+
+unsigned int yahoo_makeint(unsigned char *data);
+char **yahoo_list2array(char *buff);
+void yahoo_arraykill(char **array);
+char *yahoo_array2list(char **array);
+struct yahoo_context *yahoo_init(char *user, char *password,
+
+	struct yahoo_options *options);
+void yahoo_free_context(struct yahoo_context *ctx);
+char *yahoo_get_status_string(int statuscode);
+char *yahoo_get_status_append(int statuscode);
+char *yahoo_get_service_string(int servicecode);
+int yahoo_fetchcookies(struct yahoo_context *ctx);
+int yahoo_add_buddy(struct yahoo_context *ctx, char *addid, char *active_id,
+	char *group, char *msg);
+int yahoo_remove_buddy(struct yahoo_context *ctx, char *addid,
+	char *active_id, char *group, char *msg);
+int yahoo_get_config(struct yahoo_context *ctx);
+int yahoo_cmd_logon(struct yahoo_context *ctx, unsigned int initial_status);
+int yahoo_connect(struct yahoo_context *ctx);
+int yahoo_sendcmd_http(struct yahoo_context *ctx,
+
+	struct yahoo_rawpacket *pkt);
+int yahoo_sendcmd(struct yahoo_context *ctx, int service, char *active_nick,
+	char *content, unsigned int msgtype);
+int yahoo_cmd_ping(struct yahoo_context *ctx);
+int yahoo_cmd_idle(struct yahoo_context *ctx);
+int yahoo_cmd_sendfile(struct yahoo_context *ctx, char *active_user,
+	char *touser, char *msg, char *filename);
+int yahoo_cmd_msg(struct yahoo_context *ctx, char *active_user, char *touser,
+
+	char *msg);
+int yahoo_cmd_msg_offline(struct yahoo_context *ctx, char *active_user,
+	char *touser, char *msg);
+int yahoo_cmd_set_away_mode(struct yahoo_context *ctx, int status, char *msg);
+int yahoo_cmd_set_back_mode(struct yahoo_context *ctx, int status, char *msg);
+int yahoo_cmd_activate_id(struct yahoo_context *ctx, char *newid);
+int yahoo_cmd_user_status(struct yahoo_context *ctx);
+int yahoo_cmd_logoff(struct yahoo_context *ctx);
+int yahoo_cmd_start_conf(struct yahoo_context *ctx, char *conf_id,
+	char **userlist, char *msg, int type);
+int yahoo_cmd_conf_logon(struct yahoo_context *ctx, char *conf_id,
+
+	char *host, char **userlist);
+int yahoo_cmd_decline_conf(struct yahoo_context *ctx, char *conf_id,
+	char *host, char **userlist, char *msg);
+int yahoo_cmd_conf_logoff(struct yahoo_context *ctx, char *conf_id,
+
+	char **userlist);
+int yahoo_cmd_conf_invite(struct yahoo_context *ctx, char *conf_id,
+	char **userlist, char *invited_user, char *msg);
+int yahoo_cmd_conf_msg(struct yahoo_context *ctx, char *conf_id,
+	char **userlist, char *msg);
+void yahoo_free_rawpacket(struct yahoo_rawpacket *pkt);
+void yahoo_free_packet(struct yahoo_packet *pkt);
+void yahoo_free_idstatus(struct yahoo_idstatus *idstatus);
+struct yahoo_packet *yahoo_parsepacket(struct yahoo_context *ctx,
+
+	struct yahoo_rawpacket *inpkt);
+int yahoo_parsepacket_ping(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt);
+int yahoo_parsepacket_newmail(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt);
+int yahoo_parsepacket_grouprename(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt);
+int yahoo_parsepacket_conference_invite(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt);
+int yahoo_parsepacket_conference_decline(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt);
+int yahoo_parsepacket_conference_addinvite(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt);
+int yahoo_parsepacket_conference_msg(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt);
+int yahoo_parsepacket_conference_user(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt);
+int yahoo_parsepacket_filetransfer(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt);
+int yahoo_parsepacket_calendar(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt);
+int yahoo_parsepacket_chatinvite(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt);
+int yahoo_parsepacket_newcontact(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt);
+int yahoo_parsepacket_status(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt);
+int yahoo_parsepacket_message(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt);
+int yahoo_parsepacket_message_offline(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt);
+int yahoo_getdata(struct yahoo_context *ctx);
+struct yahoo_rawpacket *yahoo_getpacket(struct yahoo_context *ctx);
+int yahoo_isbuddy(struct yahoo_context *ctx, const char *id);
+void yahoo_freeaddressbook(struct yahoo_context *ctx);
+int yahoo_fetchaddressbook(struct yahoo_context *ctx);
+
+#endif /* CFH_LIBYAHOO_PROTO */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/yay/libyahoo.c	Fri Nov 03 10:03:53 2000 +0000
@@ -0,0 +1,3600 @@
+/*
+   Yahoo Pager Client Library
+
+   This code is based on code by Douglas Winslow. The original info from
+   his code is listed below. This code has taken his code and has been
+   altered to my naming and coding conventions and has been made more
+   usable as a library of routines.
+
+   -- Nathan Neulinger <nneul@umr.edu>
+ */
+
+/*
+   Yahoo Pager Client Emulator Pro - yppro.c
+   A basic reference implementation
+   Douglas Winslow <douglas@min.net>
+   Tue Sep  1 02:28:21 EDT 1998
+   Version 2, Revision 2
+   Known to compile on Linux 2.0, FreeBSD 2.2, and BSDi 3.0.
+   hi to aap bdc drw jfn jrc mm mcd [cejn]b #cz and rootshell
+
+   Finally!
+   Yahoo finally patched their server-side, and things will be getting
+   back to "normal".  I will continue to maintain this code as long as
+   there is interest for it.  Since Yahoo will be discontinuing YPNS1.1
+   login support shortly, I've upgraded this client to do YPNS1.2.  You
+   *must* have a password to pass authentication to the pager server.
+   This authentication is done by a weird HTTP cookie method.
+
+   This code is distributed under the GNU General Public License (GPL)
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#if defined(WITH_GTK)
+#include <gtk/gtk.h>
+#endif
+#include <unistd.h>
+#if defined(HAVE_STRINGS_H)
+#include <strings.h>
+#endif
+#if defined(HAVE_STRING_H)
+#include <string.h>
+#endif
+#include <ctype.h>
+#include "libyahoo.h"
+#ifdef HAVE_DMALLOC
+#include "dmalloc.h"
+#else
+#include <stdlib.h>
+#endif
+
+#include "memtok.h"
+
+/* allow libyahoo to be used without gtkyahoo's debug support */
+#ifdef ENABLE_LIBYAHOO_DEBUG
+#include "libyahoo-debug.h"
+#else
+static void yahoo_dbg_Print(char *tmp, ...)
+{
+}
+
+#define yahoo_dbg_NullCheck(x) ((x)?(x):("[NULL]"))
+#endif
+
+/* remap functions to gtk versions */
+#if defined(WITH_GTK)
+#define malloc g_malloc
+#define free g_free
+#define calloc(x,y) g_malloc0((x)*(y))
+#endif
+
+#if (!defined(TRUE) || !defined(FALSE))
+# define TRUE 1
+# define FALSE 0
+#endif
+
+/* Define a quick shortcut function to free a pointer and set it to null */
+#define FREE(x) if (x) { free(x); x=NULL; }
+
+#if defined(WITH_SOCKS4)
+void SOCKSinit(char *argv0);
+#endif
+
+/* pager server host */
+#define YAHOO_PAGER_HOST "cs.yahoo.com"
+#define YAHOO_PAGER_PORT	5050
+/* pager server host for http connections */
+#define YAHOO_PAGER_HTTP_HOST "http.pager.yahoo.com"
+#define YAHOO_PAGER_HTTP_PORT 80
+/* authentication/login host */
+#define YAHOO_AUTH_HOST		"msg.edit.yahoo.com"
+#define YAHOO_AUTH_PORT		80
+/* buddy/identity/config host */
+#define YAHOO_DATA_HOST		YAHOO_AUTH_HOST
+#define YAHOO_DATA_PORT     80
+/* Address book host */
+#define YAHOO_ADDRESS_HOST "uk.address.yahoo.com"
+#define YAHOO_ADDRESS_PORT	80
+
+/* User agent to use for HTTP connections */
+/* It needs to have Mozilla/4 in it, otherwise it fails */
+#ifndef VERSION
+#define VERSION "1.0"
+#endif
+#define YAHOO_USER_AGENT	"Mozilla/4.6 (libyahoo/" VERSION ")"
+
+#define YAHOO_PROTOCOL_HEADER "YPNS2.0"
+
+/*
+ *  Routines and data private to this library, should not be directly
+ *  accessed outside of these routines.
+ */
+
+/* Service code labels for debugging output */
+static struct yahoo_idlabel yahoo_service_codes[] = {
+	{YAHOO_SERVICE_LOGON, "Pager Logon"},
+	{YAHOO_SERVICE_LOGOFF, "Pager Logoff"},
+	{YAHOO_SERVICE_ISAWAY, "Is Away"},
+	{YAHOO_SERVICE_ISBACK, "Is Back"},
+	{YAHOO_SERVICE_IDLE, "Idle"},
+	{YAHOO_SERVICE_MESSAGE, "Message"},
+	{YAHOO_SERVICE_IDACT, "Activate Identity"},
+	{YAHOO_SERVICE_IDDEACT, "Deactivate Identity"},
+	{YAHOO_SERVICE_MAILSTAT, "Mail Status"},
+	{YAHOO_SERVICE_USERSTAT, "User Status"},
+	{YAHOO_SERVICE_NEWMAIL, "New Mail"},
+	{YAHOO_SERVICE_CHATINVITE, "Chat Invitation"},
+	{YAHOO_SERVICE_CALENDAR, "Calendar Reminder"},
+	{YAHOO_SERVICE_NEWPERSONALMAIL, "New Personals Mail"},
+	{YAHOO_SERVICE_NEWCONTACT, "New Friend"},
+	{YAHOO_SERVICE_GROUPRENAME, "Group Renamed"},
+	{YAHOO_SERVICE_ADDIDENT, "Add Identity"},
+	{YAHOO_SERVICE_ADDIGNORE, "Add Ignore"},
+	{YAHOO_SERVICE_PING, "Ping"},
+	{YAHOO_SERVICE_SYSMESSAGE, "System Message"},
+	{YAHOO_SERVICE_CONFINVITE, "Conference Invitation"},
+	{YAHOO_SERVICE_CONFLOGON, "Conference Logon"},
+	{YAHOO_SERVICE_CONFDECLINE, "Conference Decline"},
+	{YAHOO_SERVICE_CONFLOGOFF, "Conference Logoff"},
+	{YAHOO_SERVICE_CONFMSG, "Conference Message"},
+	{YAHOO_SERVICE_CONFADDINVITE, "Conference Additional Invitation"},
+	{YAHOO_SERVICE_CHATLOGON, "Chat Logon"},
+	{YAHOO_SERVICE_CHATLOGOFF, "Chat Logoff"},
+	{YAHOO_SERVICE_CHATMSG, "Chat Message"},
+	{YAHOO_SERVICE_GAMELOGON, "Game Logon"},
+	{YAHOO_SERVICE_GAMELOGOFF, "Game Logoff"},
+	{YAHOO_SERVICE_FILETRANSFER, "File Transfer"},
+	{YAHOO_SERVICE_PASSTHROUGH2, "Passthrough 2"},
+	{0, NULL}
+};
+
+/* Status codes */
+static struct yahoo_idlabel yahoo_status_codes[] = {
+	{YAHOO_STATUS_AVAILABLE, "I'm Available"},
+	{YAHOO_STATUS_BRB, "Be Right Back"},
+	{YAHOO_STATUS_BUSY, "Busy"},
+	{YAHOO_STATUS_NOTATHOME, "Not at Home"},
+	{YAHOO_STATUS_NOTATDESK, "Not at my Desk"},
+	{YAHOO_STATUS_NOTINOFFICE, "Not in the Office"},
+	{YAHOO_STATUS_ONPHONE, "On the Phone"},
+	{YAHOO_STATUS_ONVACATION, "On Vacation"},
+	{YAHOO_STATUS_OUTTOLUNCH, "Out to Lunch"},
+	{YAHOO_STATUS_STEPPEDOUT, "Stepped Out"},
+	{YAHOO_STATUS_INVISIBLE, "Invisible"},
+	{YAHOO_STATUS_IDLE, "Idle"},
+	{YAHOO_STATUS_CUSTOM, "Custom Message"},
+	{0, NULL}
+};
+
+/* Status codes */
+static struct yahoo_idlabel yahoo_status_append[] = {
+	{YAHOO_STATUS_AVAILABLE, "is now available"},
+	{YAHOO_STATUS_BRB, "will be right back"},
+	{YAHOO_STATUS_BUSY, "is now busy"},
+	{YAHOO_STATUS_NOTATHOME, "is not at home"},
+	{YAHOO_STATUS_NOTATDESK, "is not at their desk"},
+	{YAHOO_STATUS_NOTINOFFICE, "is not in the office"},
+	{YAHOO_STATUS_ONPHONE, "is on the phone"},
+	{YAHOO_STATUS_ONVACATION, "is on vacation"},
+	{YAHOO_STATUS_OUTTOLUNCH, "is out to lunch"},
+	{YAHOO_STATUS_STEPPEDOUT, "has stepped out"},
+	{YAHOO_STATUS_INVISIBLE, "is now invisible"},
+	{YAHOO_STATUS_IDLE, "is now idle"},
+	{YAHOO_STATUS_CUSTOM, ""},
+	{0, NULL}
+};
+
+/* Take a 4-byte character string in little-endian format and return
+   a unsigned integer */
+unsigned int yahoo_makeint(unsigned char *data)
+{
+	if (data)
+	{
+		return ((data[3] << 24) + (data[2] << 16) + (data[1] << 8) +
+			(data[0]));
+	}
+	return 0;
+}
+
+/* Take an integer and store it into a 4 character little-endian string */
+static void yahoo_storeint(unsigned char *data, unsigned int val)
+{
+	unsigned int tmp = val;
+	int i;
+
+	if (data)
+	{
+		for (i = 0; i < 4; i++)
+		{
+			data[i] = tmp % 256;
+			tmp >>= 8;
+		}
+	}
+}
+
+/*
+   converts a comma seperated list to an array of strings
+   used primarily in conference code
+
+   allocates a string in here -- caller needs to free it
+ */
+char **yahoo_list2array(char *buff)
+{
+	char **tmp_array = NULL;
+	char *array_elem = NULL;
+	char *tmp = NULL;
+
+	char *buffer = 0;
+	char *ptr_buffer = 0;
+
+	int sublen = 0;
+	int cnt = 0;
+	int nxtelem = 0;
+	unsigned int i = 0;
+	unsigned int len = 0;
+
+	if (0 == buff)
+		return 0;
+
+	buffer = strdup(buff);		/* play with a copy */
+	ptr_buffer = buffer;
+
+	/* count the number of users (commas + 1) */
+	for (i = 0; i < strlen(buffer); i++)
+	{
+		if (buffer[i] == ',')
+		{
+			/*
+			   if not looking at end of list
+			   ( ignore extra pesky comma at end of list)
+			 */
+			if (i != (strlen(buffer) - 1))
+				cnt++;
+		}
+	}
+
+	/* add one more name than comma .. */
+	cnt++;
+
+	/* allocate the array to hold the list of buddys */
+	/* null terminated array of pointers */
+	tmp_array = (char **) malloc(sizeof(char *) * (cnt + 1));
+
+	memset(tmp_array, 0, (sizeof(char *) * (cnt + 1)));
+
+	/* Parse through the list and get all the entries */
+	while ((ptr_buffer[sublen] != ',') && (ptr_buffer[sublen] != '\0'))
+		sublen++;
+	tmp = (char *) malloc(sizeof(char) * (sublen + 1));
+
+	memcpy(tmp, ptr_buffer, sublen);
+	tmp[sublen] = '\0';
+
+	if (ptr_buffer[sublen] != '\0')
+		ptr_buffer = &(ptr_buffer[sublen + 1]);
+	else
+		ptr_buffer = &(ptr_buffer[sublen]);	/* stay at the null char */
+	sublen = 0;
+
+	while (tmp && (strcmp(tmp, "") != 0))
+	{
+		len = strlen(tmp);
+		array_elem = (char *) malloc(sizeof(char) * (len + 1));
+
+		strncpy(array_elem, tmp, (len + 1));
+		array_elem[len] = '\0';
+
+		tmp_array[nxtelem++] = array_elem;
+		array_elem = NULL;
+
+		FREE(tmp);
+
+		while ((ptr_buffer[sublen] != ',') && (ptr_buffer[sublen] != '\0'))
+			sublen++;
+		tmp = (char *) malloc(sizeof(char) * (sublen + 1));
+
+		memcpy(tmp, ptr_buffer, sublen);
+		tmp[sublen] = '\0';
+
+		if (ptr_buffer[sublen] != '\0')
+			ptr_buffer = &(ptr_buffer[sublen + 1]);
+		else
+			ptr_buffer = &(ptr_buffer[sublen]);	/* stay at the null char */
+
+		sublen = 0;
+	}
+	tmp_array[nxtelem] = NULL;
+
+	FREE(tmp);
+	FREE(buffer);
+	return (tmp_array);
+
+}								/* yahoo_list2array() */
+
+/*
+ Free's the memory associated with an array generated bu yahoo_list2array
+ */
+void yahoo_arraykill(char **array)
+{
+	int nxtelem = 0;
+
+	if (NULL == array)
+		return;
+
+	while (array[nxtelem] != NULL)
+	{
+		free(array[nxtelem++]);
+	}
+
+	free(array);
+}								/* yahoo_arraykill() */
+
+/*
+   converts an array of strings to a comma seperated list
+   used primarily in conference code
+
+   allocates a string in here.. needs to be freed by caller program
+ */
+char *yahoo_array2list(char **array)
+{
+	char *list = NULL;
+	int nxtelem = 0;
+	int arraylength = 0;
+
+	if (NULL == array)
+		return NULL;
+
+	while (array[nxtelem] != NULL)
+	{
+		arraylength += strlen(array[nxtelem++]);
+		arraylength++;			/* comma */
+	}
+
+	nxtelem = 0;				/* reset array counter */
+
+	/* allocate at least one - for NULL list - and to
+	   allow my strcat to write past the end for the
+	   last comma which gets converted to NULL */
+	list = (char *) malloc(sizeof(char) * (arraylength + 1));
+
+	memset(list, 0, (arraylength + 1));
+
+	while (array[nxtelem] != NULL)
+	{
+		strcat(list, array[nxtelem++]);
+		strcat(list, ",");
+	}
+	/*
+	   overwrite last ',' with a NULL
+	   makes the string end with two null characters, but this way
+	   handles empty lists gracefully
+	 */
+	list[arraylength - 1] = '\0';
+
+	return (list);
+}								/* yahoo_array2list() */
+
+/* Free a buddy list */
+static void yahoo_free_buddies(struct yahoo_context *ctx)
+{
+	int i;
+
+	if (!ctx->buddies)
+	{
+		return;
+	}
+
+	i = 0;
+	while (ctx->buddies[i])
+	{
+		FREE(ctx->buddies[i]->group);
+		FREE(ctx->buddies[i]->id);
+		i++;
+	}
+
+	FREE(ctx->buddies);
+}
+
+/* Free a identities list */
+static void yahoo_free_identities(struct yahoo_context *ctx)
+{
+	int i;
+
+	if (!ctx->identities)
+	{
+		return;
+	}
+
+	i = 0;
+	while (ctx->identities[i])
+	{
+		FREE(ctx->identities[i]);
+		i++;
+	}
+
+	FREE(ctx->identities);
+	yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_free_identities: done\n");
+}
+
+#if 0							/* not used at the moment */
+static void yahoo_hexdump(char *label, unsigned char *data, int datalen)
+{
+	int i, j;
+	int val, skipped_last;
+	char current[100];
+	char last[100];
+	char tmp[15];
+	char outline[100];
+	static int last_datalen = 0;
+	static unsigned char *last_data = NULL;
+
+	if (last_data)
+	{
+		if (last_datalen == datalen && !memcmp(data, last_data, datalen))
+		{
+			printf("\n%s: <same as last dump>\n", label);
+			return;
+		}
+		FREE(last_data);
+	}
+
+	/* Copy the packet so we can don't duplicate it next time. */
+	last_datalen = datalen;
+	last_data = (unsigned char *) malloc(datalen);
+	memcpy(last_data, data, datalen);
+
+	/* Handle printing the full entry out */
+	printf("\n");
+	printf("%s:\n", label);
+
+	skipped_last = 0;
+	last[0] = 0;
+	for (j = 0; j * 16 < datalen; j++)
+	{
+		current[0] = 0;
+
+		/* Print out in hex */
+		for (i = j * 16; i < (j * 16 + 16); i++)
+		{
+			if (i < datalen)
+			{
+				val = data[i];
+				sprintf(tmp, "%.2X ", val);
+			}
+			else
+			{
+				sprintf(tmp, "   ");
+			}
+			strcat(current, tmp);
+		}
+
+		/* Print out in ascii */
+		strcat(current, "  ");
+		for (i = j * 16; i < (j * 16) + 16; i++)
+		{
+			if (i < datalen)
+			{
+				if (isprint(data[i]))
+				{
+					sprintf(tmp, "%c", data[i]);
+				}
+				else
+				{
+					sprintf(tmp, ".");
+				}
+			}
+			else
+			{
+				sprintf(tmp, " ");
+			}
+			strcat(current, tmp);
+		}
+
+		outline[0] = 0;
+		if (!strcmp(current, last))
+		{
+			if (!skipped_last)
+			{
+				strcpy(outline, " ....:\n");
+			}
+			skipped_last = 1;
+		}
+		else
+		{
+			sprintf(outline, " %.4d:  %s\n", j * 16, current);
+			skipped_last = 0;
+		}
+		printf("%s", outline);
+		strcpy(last, current);
+	}
+
+	if (skipped_last)
+	{
+		printf("%s", outline);
+	}
+	printf("\n");
+}
+#endif
+
+static int yahoo_socket_connect(struct yahoo_context *ctx, char *host,
+	int port)
+{
+	struct sockaddr_in serv_addr;
+	struct hostent *server;
+	int servfd;
+	int res;
+
+	yahoo_dbg_Print("libyahoo",
+		"[libyahoo] yahoo_socket_connect - starting [%s:%d]\n", host, port);
+
+	if (!ctx || !host || !port)
+	{
+		yahoo_dbg_Print("libyahoo",
+			"[libyahoo] yahoo_socket_connect - nulls\n");
+		return 0;
+	}
+
+	server = gethostbyname(host);
+	if (!server)
+	{
+		printf("[libyahoo] failed to look up server (%s:%d)\n", host, port);
+		return (0);
+	}
+
+	servfd = socket(AF_INET, SOCK_STREAM, 0);
+
+	bzero(&serv_addr, sizeof(serv_addr));
+	serv_addr.sin_family = AF_INET;
+	bcopy(server->h_addr, &serv_addr.sin_addr.s_addr, server->h_length);
+	serv_addr.sin_port = htons(port);
+
+	res = -1;
+	if (ctx->connect_mode == YAHOO_CONNECT_SOCKS4)
+	{
+#if defined(WITH_SOCKS4)
+		res =
+			Rconnect(servfd, (struct sockaddr *) &serv_addr,
+			sizeof(serv_addr));
+#endif
+	}
+	else if (ctx->connect_mode == YAHOO_CONNECT_SOCKS5)
+	{
+#if defined(WITH_SOCKS5)
+#endif
+	}
+	else if (ctx->connect_mode == YAHOO_CONNECT_NORMAL ||
+		ctx->connect_mode == YAHOO_CONNECT_HTTP ||
+		ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
+	{
+		res =
+			connect(servfd, (struct sockaddr *) &serv_addr,
+			sizeof(serv_addr));
+	}
+	else
+	{
+		printf("[libyahoo] unhandled connect mode (%d).\n",
+			ctx->connect_mode);
+		return (0);
+	}
+
+	if (res < 0)
+	{
+		close(servfd);
+		servfd = 0;
+		printf("[libyahoo] failed to connect to server (%s:%d)\n", host,
+			port);
+		return (0);
+	}
+
+	yahoo_dbg_Print("libyahoo",
+		"[libyahoo] yahoo_socket_connect - finished\n");
+	return servfd;
+}
+
+/* really ugly brute force approach - someone find a GPL'd/free
+   equivalent and replace this p.o.s. */
+static char *yahoo_urlencode(char *data)
+{
+	static char *tmp = NULL;
+	char buf[4];
+	int i, len;
+
+	len = 3 * strlen(data) + 1;
+
+	FREE(tmp);
+
+	if (!data)
+	{
+		return NULL;
+	}
+
+	/* change this at some point to re-use the buffer, no sense
+	   allocating repeatedly */
+	tmp = (char *) malloc(len);
+	tmp[0] = 0;
+
+	for (i = 0; i < strlen(data); i++)
+	{
+		if (isdigit((int) (data[i])) ||
+			isalpha((int) data[i]) || data[i] == '_')
+		{
+			buf[0] = data[i];
+			buf[1] = 0;
+			strcat(tmp, buf);
+		}
+		else
+		{
+			sprintf(buf, "%%%.2X", data[i]);
+			strcat(tmp, buf);
+		}
+	}
+
+	return tmp;
+}
+
+static void yahoo_addtobuffer(struct yahoo_context *ctx, char *data,
+	int datalen)
+{
+	//yahoo_hexdump("yahoo_addtobuffer", data, datalen);
+
+	/* Check buffer, increase size if necessary */
+	if (!ctx->io_buf
+		|| ((ctx->io_buf_maxlen - ctx->io_buf_curlen) < (datalen + 100)))
+	{
+		char *new_io_buf;
+
+		if (datalen < 10240)
+		{
+			ctx->io_buf_maxlen += 10240;
+		}
+		else
+		{
+			ctx->io_buf_maxlen += datalen;
+		}
+		new_io_buf = (char *) malloc(ctx->io_buf_maxlen);
+
+		if (ctx->io_buf)
+		{
+			memcpy(new_io_buf, ctx->io_buf, ctx->io_buf_curlen);
+			FREE(ctx->io_buf);
+		}
+
+		ctx->io_buf = new_io_buf;
+	}
+
+	memcpy(ctx->io_buf + ctx->io_buf_curlen, data, datalen);
+	ctx->io_buf_curlen += datalen;
+}
+
+static int yahoo_tcp_readline(char *ptr, int maxlen, int fd)
+{
+	int n, rc;
+	char c;
+
+	for (n = 1; n < maxlen; n++)
+	{
+	  again:
+
+		if ((rc = read(fd, &c, 1)) == 1)
+		{
+			*ptr++ = c;
+			if (c == '\n')
+				break;
+		}
+		else if (rc == 0)
+		{
+			if (n == 1)
+				return (0);		/* EOF, no data */
+			else
+				break;			/* EOF, w/ data */
+		}
+		else
+		{
+			if (errno == EINTR)
+				goto again;
+			printf
+				("Yahoo: Error reading from socket in yahoo_tcp_readline.\n");
+			exit(1);
+		}
+	}
+
+	*ptr = 0;
+	return (n);
+}
+
+/*
+ * Published library interfaces
+ */
+
+/* Initialize interface to yahoo library, sortof like a class object
+   creation routine. */
+struct yahoo_context *yahoo_init(char *user, char *password,
+	struct yahoo_options *options)
+{
+	struct yahoo_context *tmp;
+
+	if (!user || !password)
+	{
+		return NULL;
+	}
+
+	/* Allocate a new context */
+	tmp = (struct yahoo_context *) calloc(1, sizeof(*tmp));
+
+	/* Fill in any available info */
+	tmp->user = strdup(user);
+	tmp->password = strdup(password);
+	if (options->proxy_host)
+	{
+		tmp->proxy_host = strdup(options->proxy_host);
+	}
+	tmp->proxy_port = options->proxy_port;
+	tmp->connect_mode = options->connect_mode;
+
+#if defined(WITH_SOCKS4)
+	if (connect_mode == YAHOO_CONNECT_SOCKS4)
+	{
+		static int did_socks_init = 0;
+
+		if (did_socks_init == 0)
+		{
+			SOCKSinit("libyahoo");
+			did_socks_init = 1;
+		}
+	}
+#endif
+
+	/* Fetch the cookies */
+	if (!yahoo_fetchcookies(tmp))
+	{
+		yahoo_free_context(tmp);
+		return NULL;
+	}
+
+	return tmp;
+}
+
+/* Free a yahoo context */
+void yahoo_free_context(struct yahoo_context *ctx)
+{
+	FREE(ctx->user);
+	FREE(ctx->password);
+	FREE(ctx->proxy_host);
+	FREE(ctx->io_buf);
+	FREE(ctx->cookie);
+	FREE(ctx->login_cookie);
+	FREE(ctx->login_id);
+
+	yahoo_free_buddies(ctx);
+	yahoo_free_identities(ctx);
+
+	FREE(ctx);
+}
+
+/* Turn a status code into it's corresponding string */
+char *yahoo_get_status_string(int statuscode)
+{
+	int i;
+
+	for (i = 0; yahoo_status_codes[i].label; i++)
+	{
+		if (yahoo_status_codes[i].id == statuscode)
+		{
+			return yahoo_status_codes[i].label;
+		}
+	}
+	return NULL;
+}
+
+/* Turn a status code into it's corresponding string */
+char *yahoo_get_status_append(int statuscode)
+{
+	int i;
+
+	for (i = 0; yahoo_status_append[i].label; i++)
+	{
+		if (yahoo_status_append[i].id == statuscode)
+		{
+			return yahoo_status_append[i].label;
+		}
+	}
+	return NULL;
+}
+
+/* Turn a service code into it's corresponding string */
+char *yahoo_get_service_string(int servicecode)
+{
+	int i;
+	char *name = "Unknown Service";
+	static char tmp[50];
+
+	for (i = 0; yahoo_service_codes[i].label; i++)
+	{
+		if (yahoo_service_codes[i].id == servicecode)
+		{
+			name = yahoo_service_codes[i].label;
+			break;
+		}
+	}
+
+	snprintf(tmp, 50, "(%d) %s", servicecode, name);
+	return tmp;
+}
+
+/* Return a malloc()'d copy of the users cookie */
+int yahoo_fetchcookies(struct yahoo_context *ctx)
+{
+	char buffer[5000];
+	int servfd;
+	int i;
+	int res;
+	char *tmpstr;
+
+	if (!ctx)
+	{
+		return 0;
+	}
+
+	yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_fetchcookies: starting\n");
+
+	/* Check for cached cookie */
+	if (ctx->cookie)
+	{
+		FREE(ctx->cookie);
+	}
+	if (ctx->login_cookie)
+	{
+		FREE(ctx->login_cookie);
+	}
+
+	if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
+	{
+		servfd = yahoo_socket_connect(ctx, ctx->proxy_host, ctx->proxy_port);
+	}
+	else
+	{
+		servfd = yahoo_socket_connect(ctx, YAHOO_AUTH_HOST, YAHOO_AUTH_PORT);
+	}
+	if (!servfd)
+	{
+		printf("[libyahoo] failed to connect to pager auth server.\n");
+		return (0);
+	}
+
+	strcpy(buffer, "GET ");
+	if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
+	{
+		strcat(buffer, "http://" YAHOO_AUTH_HOST);
+	}
+	strcat(buffer, "/config/ncclogin?login=");
+	if (ctx->login_id)
+	{
+		strcat(buffer, yahoo_urlencode(ctx->login_id));
+	}
+	else
+	{
+		strcat(buffer, yahoo_urlencode(ctx->user));
+	}
+	strcat(buffer, "&passwd=");
+	strcat(buffer, yahoo_urlencode(ctx->password));
+	strcat(buffer, "&n=1 HTTP/1.0\r\n");
+	strcat(buffer, "User-Agent: " YAHOO_USER_AGENT "\r\n");
+	strcat(buffer, "Host: " YAHOO_AUTH_HOST "\r\n");
+	strcat(buffer, "\r\n");
+
+	write(servfd, buffer, strlen(buffer));
+
+	yahoo_dbg_Print("libyahoo",
+		"[libyahoo] yahoo_fetchcookies: writing buffer '%s'\n", buffer);
+
+	ctx->cookie = NULL;
+	while ((res = yahoo_tcp_readline(buffer, 5000, servfd)) > 0)
+	{
+		/* strip out any non-alphas */
+		for (i = 0; i < strlen(buffer); i++)
+		{
+			if (!isprint((int) buffer[i]))
+			{
+				buffer[i] = 0;
+			}
+		}
+
+		yahoo_dbg_Print("libyahoo",
+			"[libyahoo] yahoo_fetchcookies: read buffer '%s'\n", buffer);
+
+		if (!strcasecmp(buffer, "ERROR: Invalid NCC Login"))
+		{
+			yahoo_dbg_Print("libyahoo",
+				"[libyahoo] yahoo_fetchcookies: password was invalid\n");
+			return (0);
+		}
+
+		if (!strncasecmp(buffer, "Set-Cookie: Y=", 14))
+		{
+			FREE(ctx->cookie);
+			ctx->cookie = strdup(buffer + 12);
+
+			tmpstr = strchr(ctx->cookie, ';');
+			if (tmpstr)
+			{
+				*tmpstr = '\0';
+			}
+		}
+	}
+	yahoo_dbg_Print("libyahoo",
+		"[libyahoo] yahoo_fetchcookies: closing server connection\n");
+	close(servfd);
+	servfd = 0;
+	yahoo_dbg_Print("libyahoo",
+		"[libyahoo] yahoo_fetchcookies: closed server connection\n");
+
+	if (ctx->cookie)
+	{
+		tmpstr = strstr(ctx->cookie, "n=");
+		if (tmpstr)
+		{
+			ctx->login_cookie = strdup(tmpstr + 2);
+		}
+
+		tmpstr = strchr(ctx->login_cookie, '&');
+		if (tmpstr)
+		{
+			*tmpstr = '\0';
+		}
+	}
+
+	if (ctx->cookie)
+		yahoo_dbg_Print("libyahoo",
+			"[libyahoo] yahoo_fetchcookies: cookie (%s)\n", ctx->cookie);
+	if (ctx->login_cookie)
+		yahoo_dbg_Print("libyahoo",
+			"[libyahoo] yahoo_fetchcookies: login cookie (%s)\n",
+			ctx->login_cookie);
+
+	yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_fetchcookies: done\n");
+
+	return 1;
+}
+
+/* Add a buddy to your buddy list */
+int yahoo_add_buddy(struct yahoo_context *ctx, char *addid,
+	char *active_id, char *group, char *msg)
+{
+	char buffer[5000];
+	int servfd;
+
+	if (!ctx)
+	{
+		return 0;
+	}
+
+	if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
+	{
+		yahoo_dbg_Print("libyahoo",
+			"[libyahoo] yahoo_add_buddy - connecting via proxy\n");
+		servfd = yahoo_socket_connect(ctx, ctx->proxy_host, ctx->proxy_port);
+	}
+	else
+	{
+		yahoo_dbg_Print("libyahoo",
+			"[libyahoo] yahoo_add_buddy - connecting\n");
+		servfd = yahoo_socket_connect(ctx, YAHOO_DATA_HOST, YAHOO_DATA_PORT);
+	}
+	if (!servfd)
+	{
+		yahoo_dbg_Print("libyahoo",
+			"[libyahoo] yahoo_add_buddy: failed to connect\n");
+		return (0);
+	}
+
+	strcpy(buffer, "GET ");
+	if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
+	{
+		strcat(buffer, "http://" YAHOO_DATA_HOST);
+	}
+	strcat(buffer, "/config/set_buddygrp?.bg=");
+	strcat(buffer, yahoo_urlencode(group));
+	strcat(buffer, "&.src=bl&.cmd=a&.bdl=");
+	strcat(buffer, yahoo_urlencode(addid));
+	strcat(buffer, "&.id=");
+	strcat(buffer, yahoo_urlencode(active_id));
+	strcat(buffer, "&.l=");
+	strcat(buffer, yahoo_urlencode(ctx->user));
+	strcat(buffer, "&.amsg=");
+	strcat(buffer, yahoo_urlencode(msg));
+	strcat(buffer, " HTTP/1.0\r\n");
+
+	strcat(buffer, "User-Agent: " YAHOO_USER_AGENT "\r\n");
+	strcat(buffer, "Host: " YAHOO_DATA_HOST "\r\n");
+	strcat(buffer, "Cookie: ");
+	strcat(buffer, ctx->cookie);
+	strcat(buffer, "\r\n");
+	strcat(buffer, "\r\n");
+
+	write(servfd, buffer, strlen(buffer));
+	while (yahoo_tcp_readline(buffer, 5000, servfd) > 0)
+	{
+		/* just dump the output, I don't care about errors at the moment */
+	}
+	close(servfd);
+	servfd = 0;
+
+	/* indicate success for now with 0 */
+	yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_add_buddy: finished\n");
+	return 0;
+}
+
+/* Remove a buddy from your buddy list */
+int yahoo_remove_buddy(struct yahoo_context *ctx, char *addid,
+	char *active_id, char *group, char *msg)
+{
+	char buffer[5000];
+	int servfd;
+
+	if (!ctx)
+	{
+		return 0;
+	}
+
+	if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
+	{
+		yahoo_dbg_Print("libyahoo",
+			"[libyahoo] yahoo_add_buddy - connecting via proxy\n");
+		servfd = yahoo_socket_connect(ctx, ctx->proxy_host, ctx->proxy_port);
+	}
+	else
+	{
+		yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_add_buddy - connecting\n");
+		servfd = yahoo_socket_connect(ctx, YAHOO_DATA_HOST, YAHOO_DATA_PORT);
+	}
+	if (!servfd)
+	{
+		yahoo_dbg_Print("libyahoo",
+			"[libyahoo] yahoo_add_buddy: failed to connect\n");
+		return (0);
+	}
+
+	strcpy(buffer, "GET ");
+	if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
+	{
+		strcat(buffer, "http://" YAHOO_DATA_HOST);
+	}
+	strcat(buffer, "/config/set_buddygrp?.bg=");
+	strcat(buffer, yahoo_urlencode(group));
+	strcat(buffer, "&.src=bl&.cmd=d&.bdl=");
+	strcat(buffer, yahoo_urlencode(addid));
+	strcat(buffer, "&.id=");
+	strcat(buffer, yahoo_urlencode(active_id));
+	strcat(buffer, "&.l=");
+	strcat(buffer, yahoo_urlencode(ctx->user));
+	strcat(buffer, "&.amsg=");
+	strcat(buffer, yahoo_urlencode(msg));
+	strcat(buffer, " HTTP/1.0\r\n");
+
+	strcat(buffer, "User-Agent: " YAHOO_USER_AGENT "\r\n");
+	strcat(buffer, "Host: " YAHOO_DATA_HOST "\r\n");
+	strcat(buffer, "Cookie: ");
+	strcat(buffer, ctx->cookie);
+	strcat(buffer, "\r\n");
+	strcat(buffer, "\r\n");
+
+	write(servfd, buffer, strlen(buffer));
+	while (yahoo_tcp_readline(buffer, 5000, servfd) > 0)
+	{
+		/* just dump the output, I don't care about errors at the moment */
+	}
+	close(servfd);
+	servfd = 0;
+
+	/* indicate success for now with 0 */
+	return 0;
+}
+
+/* Retrieve the configuration from the server */
+int yahoo_get_config(struct yahoo_context *ctx)
+{
+	char buffer[5000];
+	int i, j;
+	int servfd;
+	int commas;
+	int in_section;
+	struct yahoo_buddy **buddylist = NULL;
+	int buddycnt = 0;
+	int nextbuddy = 0;
+
+	/* Check for cached cookie */
+	if (!ctx || !ctx->cookie)
+	{
+		return 0;
+	}
+
+	yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_get_config: starting\n");
+
+	if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
+	{
+		servfd = yahoo_socket_connect(ctx, ctx->proxy_host, ctx->proxy_port);
+	}
+	else
+	{
+		servfd = yahoo_socket_connect(ctx, YAHOO_DATA_HOST, YAHOO_DATA_PORT);
+	}
+	if (!servfd)
+	{
+		yahoo_dbg_Print("libyahoo",
+			"[libyahoo] yahoo_get_config: failed to connect\n");
+		return (0);
+	}
+
+	strcpy(buffer, "GET ");
+	if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
+	{
+		strcat(buffer, "http://" YAHOO_DATA_HOST);
+	}
+	strcat(buffer, "/config/get_buddylist?.src=bl HTTP/1.0\r\n");
+	strcat(buffer, "Cookie: ");
+	strcat(buffer, ctx->cookie);
+	strcat(buffer, "\r\n");
+	strcat(buffer, "\r\n");
+
+	write(servfd, buffer, strlen(buffer));
+	yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_get_config: sending '%s'\n",
+		buffer);
+
+	in_section = 0;
+	while (yahoo_tcp_readline(buffer, 5000, servfd) > 0)
+	{
+		/* strip out any non-alphas */
+		for (i = 0; i < strlen(buffer); i++)
+		{
+			if (!isprint((int) buffer[i]))
+			{
+				for (j = i; j < strlen(buffer); j++)
+				{
+					buffer[j] = buffer[j + 1];
+				}
+			}
+		}
+
+		yahoo_dbg_Print("libyahoo",
+			"[libyahoo] yahoo_get_config: read '%s'\n", buffer);
+
+		if (!strcasecmp(buffer, "BEGIN IDENTITIES"))
+		{
+			in_section = 1;
+		}
+		else if (!strcasecmp(buffer, "END IDENTITIES"))
+		{
+			in_section = 0;
+		}
+		else if (!strcasecmp(buffer, "BEGIN BUDDYLIST"))
+		{
+			in_section = 2;
+		}
+		else if (!strcasecmp(buffer, "END BUDDYLIST"))
+		{
+			in_section = 0;
+		}
+		else if (in_section == 1)
+		{
+			char *tmp;
+
+			/* count the commas */
+			commas = 0;
+			for (i = 0; i < strlen(buffer); i++)
+			{
+				if (buffer[i] == ',')
+				{
+					commas++;
+				}
+			}
+
+			/* make sure we've gotten rid of any previous identities array */
+			yahoo_free_identities(ctx);
+
+			/* allocate the array to hold the list of identities */
+			ctx->identities = (char **) calloc(commas + 2, sizeof(char *));
+
+			/* Parse through the list and get all the entries */
+			i = 0;
+			tmp = strtok(buffer, ",");
+			while (tmp)
+			{
+				yahoo_dbg_Print("libyahoo",
+					"[libyahoo] yahoo_get_config: retrieved "
+					"identity '%s'\n", tmp);
+				ctx->identities[i++] = strdup(tmp);
+				tmp = strtok(NULL, ",");
+			}
+			ctx->identities[i] = 0;
+		}
+		else if (in_section == 2)
+		{
+			char *group;
+			char *tmp;
+			struct yahoo_buddy **tmp_buddylist;
+			struct yahoo_buddy *tmpbuddy;
+			int tmp_buddycnt;
+
+			/* count the buddies on this line */
+			tmp_buddycnt = buddycnt;
+			for (i = 0; i < strlen(buffer); i++)
+			{
+				if (buffer[i] == ',')
+				{
+					buddycnt++;
+				}
+			}
+			buddycnt++;			/* always one more than comma count */
+
+			/* allocate the array to hold the list of buddy */
+			tmp_buddylist = (struct yahoo_buddy **)
+				malloc(sizeof(struct yahoo_buddy *) * (buddycnt + 1));
+
+			/* Free and copy the old one if necessary */
+			if (buddylist)
+			{
+				memcpy(tmp_buddylist, buddylist,
+
+					(tmp_buddycnt + 1) * sizeof(struct yahoo_buddy *));
+
+				FREE(buddylist);
+			}
+			buddylist = tmp_buddylist;
+
+			/* Parse through the list and get all the entries */
+			tmp = strtok(buffer, ",:");
+			group = NULL;
+			while (tmp)
+			{
+				if (tmp == buffer)	/* group name */
+				{
+					group = tmp;
+				}
+				else
+				{
+					tmpbuddy = (struct yahoo_buddy *)
+
+						malloc(sizeof(struct yahoo_buddy));
+
+					tmpbuddy->id = strdup(tmp);
+					tmpbuddy->group = strdup(group);
+					yahoo_dbg_Print("libyahoo",
+						"[libyahoo] yahoo_get_config: retrieved buddy '%s:%s'\n",
+						group, tmp);
+					buddylist[nextbuddy++] = tmpbuddy;
+				}
+				tmp = strtok(NULL, ",");
+			}
+			buddylist[nextbuddy] = 0;
+		}
+		else if (!strncasecmp(buffer, "Mail=", strlen("Mail=")))
+		{
+			ctx->mail = atoi(buffer + strlen("Mail="));
+			yahoo_dbg_Print("libyahoo",
+				"[libyahoo] yahoo_get_config: retrieved mail flag '%d'\n",
+				ctx->mail);
+		}
+		else if (!strncasecmp(buffer, "Login=", strlen("Login=")))
+		{
+			FREE(ctx->login_id);
+			ctx->login_id = strdup(buffer + strlen("Login="));
+			yahoo_dbg_Print("libyahoo",
+				"[libyahoo] yahoo_get_config: retrieved login id '%s'\n",
+				ctx->login_id);
+		}
+	}
+	close(servfd);
+	servfd = 0;
+
+	yahoo_free_buddies(ctx);
+	ctx->buddies = buddylist;
+
+	/* fill in a bogus login_in, just in case */
+	if (!ctx->login_id)
+	{
+		ctx->login_id = strdup(ctx->user);
+	}
+
+	/* refetch the cookie if the login_id is different so that
+	   it will have the correct info in it */
+	if (strcmp(ctx->login_id, ctx->user))
+	{
+		yahoo_dbg_Print("libyahoo",
+			"[libyahoo] yahoo_get_config - refetching cookies\n");
+		yahoo_fetchcookies(ctx);
+	}
+
+	yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_get_config - finished\n");
+
+	return 1;
+}
+
+/* Log in, optionally activating other secondary identities */
+int yahoo_cmd_logon(struct yahoo_context *ctx, unsigned int initial_status)
+{
+	char login_string[5000];	/* need to change to malloc ASAP */
+	char *tmpid;
+	char **identities = ctx->identities;
+	int i;
+
+	if (!ctx || !ctx->login_cookie)
+	{
+		yahoo_dbg_Print("libyahoo",
+			"[libyahoo] yahoo_cmd_logon: logon called without "
+			"context and/or cookie.\n");
+		exit(1);
+	}
+
+	strcpy(login_string, ctx->login_cookie);
+/* testing with new logon code */
+//  strcpy(login_string, "$1$_2S43d5f$XXXXXXXXWtRKNclLWyy8C.");
+
+	login_string[strlen(login_string) + 1] = 0;
+	login_string[strlen(login_string)] = 1;	/* control-A */
+
+	strcat(login_string, ctx->user);
+
+	/* Send all identities */
+	if (identities)
+	{
+		i = 0;
+		tmpid = identities[i];
+		while (tmpid)
+		{
+			if (strcasecmp(tmpid, ctx->user))
+			{
+				strcat(login_string, ",");
+				strcat(login_string, tmpid);
+			}
+			tmpid = identities[i++];
+		}
+	}
+
+	yahoo_sendcmd(ctx, YAHOO_SERVICE_LOGON, ctx->user, login_string,
+		initial_status);
+
+	/* something that the windows one sends, not sure what it is */
+#if 0
+	login_string[0] = 0;
+	strcat(login_string, "C=0\002");
+	strcat(login_string, "F=0,P=0,H=0,S=0,W=0,O=0\002");
+	strcat(login_string, "M=0,P=0,C=0,S=0");
+	yahoo_sendcmd(ctx, YAHOO_SERVICE_PASSTHROUGH2, ctx->user, login_string,
+		0);
+#endif
+
+	return 0;
+}
+
+int yahoo_connect(struct yahoo_context *ctx)
+{
+	int res;
+
+	res = 0;
+	ctx->sockfd = 0;
+
+	yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_connect - starting\n");
+
+	switch (ctx->connect_mode)
+	{
+		case YAHOO_CONNECT_SOCKS4:
+		case YAHOO_CONNECT_SOCKS5:
+		case YAHOO_CONNECT_NORMAL:
+			yahoo_dbg_Print("libyahoo",
+				"[libyahoo] yahoo_connect - establishing socket connection\n");
+			ctx->sockfd =
+				yahoo_socket_connect(ctx, YAHOO_PAGER_HOST, YAHOO_PAGER_PORT);
+			if (!ctx->sockfd)
+			{
+				printf("[libyahoo] couldn't connect to pager host\n");
+				return (0);
+			}
+			break;
+
+		case YAHOO_CONNECT_HTTP:
+		case YAHOO_CONNECT_HTTPPROXY:
+			yahoo_dbg_Print("libyahoo",
+				"[libyahoo] yahoo_connect - no connect for HTTP\n");
+			/* no pager connection will be established for this */
+			break;
+
+		default:
+			printf("[libyahoo] unhandled connect mode (%d)\n",
+				ctx->connect_mode);
+	}
+
+	yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_connect - finished\n");
+	return (1);
+}
+
+/* Send a packet to the server via http connection method */
+/* at moment only handles regular http connection, once I have that
+   working, this code needs to also do http proxy connections as well */
+int yahoo_sendcmd_http(struct yahoo_context *ctx, struct yahoo_rawpacket *pkt)
+{
+	int sockfd;
+	char buffer[5000];
+	char tmpbuf[1000];
+	int size;
+	int res;
+
+	if (!ctx || !pkt)
+	{
+		return (0);
+	}
+
+	size = YAHOO_PACKET_HEADER_SIZE + strlen(pkt->content) + 1;
+
+	if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
+	{
+		sockfd = yahoo_socket_connect(ctx, ctx->proxy_host, ctx->proxy_port);
+	}
+	else
+	{
+		sockfd = yahoo_socket_connect(ctx, YAHOO_PAGER_HTTP_HOST,
+			YAHOO_PAGER_HTTP_PORT);
+	}
+	if (!sockfd)
+	{
+		printf("[libyahoo] failed to connect to pager http server.\n");
+		return (0);
+	}
+
+	strcpy(buffer, "POST ");
+	if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
+	{
+		strcat(buffer, "http://" YAHOO_PAGER_HTTP_HOST);
+	}
+	strcat(buffer, "/notify HTTP/1.0\r\n");
+
+	strcat(buffer, "User-Agent: " YAHOO_USER_AGENT "\r\n");
+	strcat(buffer, "Host: " YAHOO_PAGER_HTTP_HOST "\r\n");
+	snprintf(tmpbuf, 1000, "Content-Length: %d\r\n", size);
+	strcat(buffer, tmpbuf);
+
+	strcat(buffer, "Pragma: No-Cache\r\n");
+
+	strcat(buffer, "Cookie: ");
+	strcat(buffer, ctx->cookie);
+	strcat(buffer, "\r\n");
+	strcat(buffer, "\r\n");
+
+	write(sockfd, buffer, strlen(buffer));
+	write(sockfd, pkt, size);
+	write(sockfd, "\r\n", 2);
+
+	/* now we need to read the results */
+	/* I'm taking the cheat approach and just dumping them onto the
+	   buffer, headers and all, the _skip_to_YHOO_ code will handle it
+	   for now */
+
+	while ((res = read(sockfd, buffer, 5000)) > 0)
+	{
+		if (res == -1)
+		{
+			printf("[libyahoo] Error reading data from server.\n");
+			exit(1);
+		}
+		yahoo_addtobuffer(ctx, buffer, res);
+	}
+	close(sockfd);
+	sockfd = 0;
+
+	return (0);
+}
+
+/* Send a packet to the server, called by all routines that want to issue
+   a command. */
+int yahoo_sendcmd(struct yahoo_context *ctx, int service, char *active_nick,
+	char *content, unsigned int msgtype)
+{
+	int size;
+	struct yahoo_rawpacket *pkt;
+	int maxcontentsize;
+
+	/* why the )&*@#$( did they hardwire the packet size that gets sent
+	   when the size of the packet is included in what is sent, bizarre */
+	size = 4 * 256 + YAHOO_PACKET_HEADER_SIZE;
+	pkt = (struct yahoo_rawpacket *) calloc(1, size);
+
+	/* figure out max content length, including trailing null */
+	maxcontentsize = size - sizeof(struct yahoo_rawpacket);
+
+	/* Build the packet */
+	strcpy(pkt->version, YAHOO_PROTOCOL_HEADER);
+	yahoo_storeint(pkt->len, size);
+	yahoo_storeint(pkt->service, service);
+
+	/* not sure if this is valid with YPNS1.4 or if it needs 2.0 */
+	yahoo_storeint(pkt->msgtype, msgtype);
+
+	/* Not sure, but might as well send for regular connections as well. */
+	yahoo_storeint(pkt->magic_id, ctx->magic_id);
+	strcpy(pkt->nick1, ctx->login_id);
+	strcpy(pkt->nick2, active_nick);
+	strncpy(pkt->content, content, maxcontentsize);
+
+	// yahoo_hexdump("send_cmd", (char *) pkt, size);
+
+	switch (ctx->connect_mode)
+	{
+		case YAHOO_CONNECT_SOCKS4:
+		case YAHOO_CONNECT_SOCKS5:
+		case YAHOO_CONNECT_NORMAL:
+			write(ctx->sockfd, pkt, size);
+			break;
+		case YAHOO_CONNECT_HTTP:
+		case YAHOO_CONNECT_HTTPPROXY:
+			yahoo_sendcmd_http(ctx, pkt);
+			break;
+	}
+
+	FREE(pkt);
+	return (0);
+}
+
+int yahoo_cmd_ping(struct yahoo_context *ctx)
+{
+	yahoo_sendcmd(ctx, YAHOO_SERVICE_PING, ctx->user, "", 0);
+	return (0);
+}
+
+int yahoo_cmd_idle(struct yahoo_context *ctx)
+{
+	yahoo_sendcmd(ctx, YAHOO_SERVICE_IDLE, ctx->user, "", 0);
+	return (0);
+}
+
+int yahoo_cmd_sendfile(struct yahoo_context *ctx, char *active_user,
+	char *touser, char *msg, char *filename)
+{
+	yahoo_dbg_Print("libyahoo", "yahoo_cmd_sendfile not implemented yet!");
+	return (0);
+}
+
+int yahoo_cmd_msg(struct yahoo_context *ctx, char *active_user,
+	char *touser, char *msg)
+{
+	char *content;
+
+	content = (char *) malloc(strlen(touser) + strlen(msg) + 5);
+
+	if (strlen(touser))
+	{
+		sprintf(content, "%s,%s", touser, msg);
+		yahoo_sendcmd(ctx, YAHOO_SERVICE_MESSAGE, active_user, content, 0);
+	}
+
+	FREE(content);
+	return (0);
+}
+
+int yahoo_cmd_msg_offline(struct yahoo_context *ctx, char *active_user,
+	char *touser, char *msg)
+{
+	char *content;
+
+	content = (char *) malloc(strlen(touser) + strlen(msg) + 5);
+
+	if (strlen(touser))
+	{
+		sprintf(content, "%s,%s", touser, msg);
+		yahoo_sendcmd(ctx, YAHOO_SERVICE_MESSAGE, active_user, content,
+			YAHOO_MSGTYPE_KNOWN_USER);
+	}
+
+	FREE(content);
+	return (0);
+}
+
+/* appended the " " so that won't trigger yahoo bug - hack for the moment */
+int yahoo_cmd_set_away_mode(struct yahoo_context *ctx, int status, char *msg)
+{
+	char statusstring[500];
+
+	yahoo_dbg_Print("libyahoo",
+		"[libyahoo] yahoo_cmd_set_away_mode: set status (%d), msg(%s)\n",
+		status, yahoo_dbg_NullCheck(msg));
+
+	if (status == YAHOO_STATUS_CUSTOM)
+	{
+		if (msg && msg[0] != 0)
+		{
+			snprintf(statusstring, 500, "%d%c%s", status, 1, msg);
+		}
+		else
+		{
+			snprintf(statusstring, 500, "%d%c---", status, 1);
+		}
+	}
+	else
+	{
+		snprintf(statusstring, 500, "%d", status);
+	}
+	yahoo_sendcmd(ctx, YAHOO_SERVICE_ISAWAY, ctx->user, statusstring, 0);
+
+	return 0;
+}
+
+int yahoo_cmd_set_back_mode(struct yahoo_context *ctx, int status, char *msg)
+{
+	char statusstring[500];
+
+	yahoo_dbg_Print("libyahoo",
+		"[libyahoo] yahoo_cmd_set_back_mode: set status (%d), msg(%s)\n",
+		status, yahoo_dbg_NullCheck(msg));
+
+	snprintf(statusstring, 500, "%d%c%s ", status, 1, msg ? msg : "");
+	yahoo_sendcmd(ctx, YAHOO_SERVICE_ISBACK, ctx->user, statusstring, 0);
+
+	return 0;
+}
+
+int yahoo_cmd_activate_id(struct yahoo_context *ctx, char *newid)
+{
+	if (strlen(newid))
+	{
+		yahoo_sendcmd(ctx, YAHOO_SERVICE_IDACT, newid, newid, 0);
+	}
+	return (0);
+}
+
+int yahoo_cmd_user_status(struct yahoo_context *ctx)
+{
+	yahoo_sendcmd(ctx, YAHOO_SERVICE_USERSTAT, ctx->user, "", 0);
+	return (0);
+}
+
+int yahoo_cmd_logoff(struct yahoo_context *ctx)
+{
+	yahoo_sendcmd(ctx, YAHOO_SERVICE_LOGOFF, ctx->user, ctx->user, 0);
+	return (0);
+}
+
+/*
+
+yahoo_cmd_start_conf()
+
+   Starts a conference. (You create the conference)
+
+Arguments:
+   char *conf_id == The conference id -- usually of the form name-number,
+                    though it doesn't seem to matter much. ex: jaylubo-123
+		    You create this id to start the conference, but pass it
+		    along after that.
+   char **userlist == Users to invite. Null terminated array of strings.
+   car *msg == Invitiation message.
+   int type == 0 - normal, 1 - voice (not supported yet)
+
+Packet format:
+   id^invited-users^msg^0or1
+*/
+int yahoo_cmd_start_conf(struct yahoo_context *ctx, char *conf_id,
+	char **userlist, char *msg, int type)
+{
+	char ctrlb = 2;
+	char *content;
+	char *new_userlist = yahoo_array2list(userlist);
+	int cont_len = 0;
+
+#ifdef ENABLE_LIBYAHOO_DEBUG
+	char *unraw_msg = NULL;
+#endif /* def ENABLE_LIBYAHOO_DEBUG */
+
+	int size = strlen(conf_id) + strlen(msg) + 8 + strlen(new_userlist);
+
+	content = (char *) malloc(size);
+	memset(content, 0, size);
+
+	cont_len = snprintf(content,
+		size - 1,
+		"%s%c%s%c%s%c%d",
+		conf_id, ctrlb, new_userlist, ctrlb, msg, ctrlb, type);
+
+#ifdef ENABLE_LIBYAHOO_DEBUG
+	unraw_msg = yahoo_unraw_buffer(content, cont_len);
+	yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_cmd_start_conf: %s\n",
+		unraw_msg);
+	free(unraw_msg);
+#endif /* def ENABLE_LIBYAHOO_DEBUG */
+	yahoo_sendcmd(ctx, YAHOO_SERVICE_CONFINVITE, ctx->user, content, 0);
+
+	FREE(new_userlist);
+	FREE(content);
+	return (0);
+}
+
+/*
+yahoo_cmd_conf_logon()
+
+   Reply to a conference invitation, logs you into conference.
+
+Arguments:
+   char *conf_id ==   The conference id -- usually of the form name-number,
+                      though it doesn't seem to matter much. ex: jaylubo-123
+		      This comes from the invitiation.
+   char *host ==      The person that sent you the invitation.
+   char **userlist == Everyone else invited. This comes from the invitiation.
+                      Null terminated array of strings.
+
+Packet format:
+   id^all-invited-users-and-host
+
+*/
+int yahoo_cmd_conf_logon(struct yahoo_context *ctx, char *conf_id,
+	char *host, char **userlist)
+{
+	char ctrlb = 2;
+	char *content;
+	char *new_userlist = yahoo_array2list(userlist);
+	int cont_len = 0;
+
+#ifdef ENABLE_LIBYAHOO_DEBUG
+	char *unraw_msg = NULL;
+#endif /* def ENABLE_LIBYAHOO_DEBUG */
+
+	int size = strlen(conf_id) + strlen(host) + 8 + strlen(new_userlist);
+
+	content = (char *) malloc(size);
+	memset(content, 0, size);
+
+	cont_len =
+		sprintf(content, "%s%c%s,%s", conf_id, ctrlb, host, new_userlist);
+
+#ifdef ENABLE_LIBYAHOO_DEBUG
+	unraw_msg = yahoo_unraw_buffer(content, cont_len);
+	yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_cmd_conf_logon: %s\n",
+		unraw_msg);
+	free(unraw_msg);
+#endif /* def ENABLE_LIBYAHOO_DEBUG */
+	yahoo_sendcmd(ctx, YAHOO_SERVICE_CONFLOGON, ctx->user, content, 0);
+
+	FREE(new_userlist);
+	FREE(content);
+	return (0);
+}
+
+/*
+
+yahoo_cmd_decline_conf()
+
+   Reply to a conference invitation, decline offer.
+
+Arguments:
+   char *conf_id ==   The conference id -- usually of the form name-number,
+                      though it doesn't seem to matter much. ex: jaylubo-123
+		      This comes from the invitiation.
+   char *host ==      The person that sent you the invitation.
+   char **userlist == Everyone else invited. This comes from the invitiation.
+                      Null terminated array of strings.
+		      (Null if replying to a conference additional invite )
+   char *msg ==       Reason for declining.
+
+Packet format:
+   id^all-invited-users-and-host^msg
+
+*/
+int yahoo_cmd_decline_conf(struct yahoo_context *ctx, char *conf_id,
+	char *host, char **userlist, char *msg)
+{
+	char ctrlb = 2;
+	char *content;
+	char *new_userlist = yahoo_array2list(userlist);
+
+	int size =
+
+		strlen(conf_id) + strlen(host) + strlen(msg) + 8 +
+		strlen(new_userlist);
+
+	content = (char *) malloc(size);
+	memset(content, 0, size);
+
+	sprintf(content, "%s%c%s,%s%c%s", conf_id, ctrlb, host, new_userlist,
+		ctrlb, msg);
+
+	yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_cmd_decline_conf: %s\n",
+		content);
+	yahoo_sendcmd(ctx, YAHOO_SERVICE_CONFDECLINE, ctx->user, content, 0);
+
+	FREE(new_userlist);
+	FREE(content);
+	return (0);
+}
+
+/*
+
+yahoo_cmd_conf_logoff()
+
+   Logoff of a conference.
+
+Arguments:
+   char *conf_id ==   The conference id -- usually of the form name-number,
+                      though it doesn't seem to matter much. ex: jaylubo-123
+		      This comes from the invitiation.
+   char **userlist == Everyone in conference.
+                      Null terminated array of strings.
+
+Packet format:
+   id^all-invited-users
+
+*/
+
+int yahoo_cmd_conf_logoff(struct yahoo_context *ctx, char *conf_id,
+	char **userlist)
+{
+	char ctrlb = 2;
+	char *content;
+	int cont_len = 0;
+
+#ifdef ENABLE_LIBYAHOO_DEBUG
+	char *unraw_msg = NULL;
+#endif /* def ENABLE_LIBYAHOO_DEBUG */
+	char *new_userlist = yahoo_array2list(userlist);
+
+	int size = strlen(conf_id) + strlen(new_userlist) + 8;
+
+	content = (char *) malloc(size);
+	memset(content, 0, size);
+
+	cont_len =
+		snprintf(content, size, "%s%c%s", conf_id, ctrlb, new_userlist);
+#ifdef ENABLE_LIBYAHOO_DEBUG
+	unraw_msg = yahoo_unraw_buffer(content, cont_len);
+	yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_cmd_conf_logoff: %s\n",
+		unraw_msg);
+	free(unraw_msg);
+#endif /* def ENABLE_LIBYAHOO_DEBUG */
+	yahoo_sendcmd(ctx, YAHOO_SERVICE_CONFLOGOFF, ctx->user, content, 0);
+
+	FREE(new_userlist);
+	FREE(content);
+	return (0);
+}
+
+/*
+
+yahoo_cmd_conf_invite()
+
+   Invite another user to an already running conference.
+
+Arguments:
+   char *conf_id ==   The conference id -- usually of the form name-number,
+                      though it doesn't seem to matter much. ex: jaylubo-123
+		      This comes from the invitiation.
+   char *invited_user == The person being invited to conference.
+   char **userlist == Everyone else in conference.
+                      Null terminated array of strings.
+   char *msg ==       Invitation message.
+
+Packet format:
+   id^invited-user^who-else-in-conf^who-else-in-conf^msg^0
+
+*/
+
+int yahoo_cmd_conf_invite(struct yahoo_context *ctx, char *conf_id,
+	char **userlist, char *invited_user, char *msg)
+{
+	char ctrlb = 2;
+	char *content;
+	char *new_userlist = yahoo_array2list(userlist);
+
+	int size = strlen(conf_id) + strlen(invited_user)
+		+ (2 * strlen(new_userlist)) + strlen(msg) + 7;
+
+	content = (char *) malloc(size);
+	memset(content, 0, size);
+
+	sprintf(content, "%s%c%s%c%s%c%s%c%s%c0", conf_id, ctrlb,
+		invited_user, ctrlb, new_userlist, ctrlb,
+		new_userlist, ctrlb, msg, ctrlb);
+	yahoo_dbg_Print("libyahoo", "[libyahoo] yahoo_cmd_conf_invite: %s\n",
+		content);
+	yahoo_sendcmd(ctx, YAHOO_SERVICE_CONFADDINVITE, ctx->user, content, 0);
+
+	FREE(new_userlist);
+	FREE(content);
+	return (0);
+}
+
+/*
+
+yahoo_cmd_conf_msg()
+
+   Send a message to everyone in conference.
+
+Arguments:
+   char *conf_id ==   The conference id -- usually of the form name-number,
+                      though it doesn't seem to matter much. ex: jaylubo-123
+		      This comes from the invitiation.
+   char **userlist == Everyone in conference.
+                      Null terminated array of strings.
+   char *msg ==       Message to send.
+
+Packet format:
+   id^all-invited-users^msg
+
+*/
+int yahoo_cmd_conf_msg(struct yahoo_context *ctx, char *conf_id,
+	char **userlist, char *msg)
+{
+	char ctrlb = 2;
+	char *content;
+	int cont_len = 0;
+
+#ifdef ENABLE_LIBYAHOO_DEBUG
+	char *unraw_msg = NULL;
+#endif /* def ENABLE_LIBYAHOO_DEBUG */
+	char *new_userlist = yahoo_array2list(userlist);
+
+	int size = strlen(conf_id) + strlen(new_userlist) + strlen(msg) + 8;
+
+	content = (char *) malloc(size);
+	memset(content, 0, size);
+
+	cont_len =
+		snprintf(content, size, "%s%c%s%c%s", conf_id, ctrlb, new_userlist,
+		ctrlb, msg);
+#ifdef ENABLE_LIBYAHOO_DEBUG
+	unraw_msg = yahoo_unraw_buffer(content, cont_len);
+	yahoo_dbg_Print("libyahoo", "yahoo_cmd_conf_msg: %s\n", unraw_msg);
+	free(unraw_msg);
+#endif /* def ENABLE_LIBYAHOO_DEBUG */
+	yahoo_sendcmd(ctx, YAHOO_SERVICE_CONFMSG, ctx->user, content, 0);
+
+	FREE(new_userlist);
+	FREE(content);
+	return (0);
+}
+
+/*
+ * Free the rawpacket structure - primarily a placeholder
+ * since all static elements at the moment
+ */
+void yahoo_free_rawpacket(struct yahoo_rawpacket *pkt)
+{
+	FREE(pkt);
+}
+
+/*
+ * Free entire packet structure including string elements
+ */
+void yahoo_free_packet(struct yahoo_packet *pkt)
+{
+	int i;
+
+	if (pkt)
+	{
+		FREE(pkt->real_id);
+		FREE(pkt->active_id);
+		FREE(pkt->conf_id);
+		FREE(pkt->conf_host);
+		FREE(pkt->conf_user);
+		FREE(pkt->conf_msg);
+		FREE(pkt->cal_url);
+		FREE(pkt->cal_timestamp);
+		FREE(pkt->cal_title);
+		FREE(pkt->cal_description);
+		FREE(pkt->chat_invite_content);
+		FREE(pkt->msg_id);
+		FREE(pkt->msg_timestamp);
+		FREE(pkt->msg);
+		FREE(pkt->file_from);
+		FREE(pkt->file_flag);
+		FREE(pkt->file_url);
+		FREE(pkt->file_description);
+		FREE(pkt->group_old);
+		FREE(pkt->group_new);
+		if (pkt->idstatus)
+		{
+			for (i = 0; i < pkt->idstatus_count; i++)
+			{
+				yahoo_free_idstatus(pkt->idstatus[i]);
+			}
+			free(pkt->idstatus);
+		}
+		free(pkt);
+	}
+}
+
+void yahoo_free_idstatus(struct yahoo_idstatus *idstatus)
+{
+	if (!idstatus)
+	{
+		return;
+	}
+
+	FREE(idstatus->id);
+	FREE(idstatus->connection_id);
+	FREE(idstatus->status_msg);
+	FREE(idstatus);
+}
+
+struct yahoo_packet *yahoo_parsepacket(struct yahoo_context *ctx,
+	struct yahoo_rawpacket *inpkt)
+{
+	struct yahoo_packet *pkt;
+
+	/* If no valid inpkt passed, return */
+	if (!inpkt)
+	{
+		return NULL;
+	}
+
+	/* Allocate the packet structure, zeroed out */
+	pkt = (struct yahoo_packet *) calloc(sizeof(*pkt), 1);
+
+	/* Pull out the standard data */
+	pkt->service = yahoo_makeint(inpkt->service);
+	pkt->connection_id = yahoo_makeint(inpkt->connection_id);
+	pkt->real_id = strdup(inpkt->nick1);
+	pkt->active_id = strdup(inpkt->nick2);
+
+	pkt->magic_id = yahoo_makeint(inpkt->magic_id);
+	pkt->unknown1 = yahoo_makeint(inpkt->unknown1);
+	pkt->msgtype = yahoo_makeint(inpkt->msgtype);
+
+	/* doing this seems like a cleaner approach, but am not sure if it is
+	   a valid one */
+	if (pkt->magic_id != 0)
+	{
+		ctx->magic_id = pkt->magic_id;
+	}
+	if (pkt->connection_id != 0)
+	{
+		ctx->connection_id = pkt->connection_id;
+	}
+
+	/* Call a particular parse routine to pull out the content */
+	switch (pkt->service)
+	{
+		case YAHOO_SERVICE_LOGON:
+		case YAHOO_SERVICE_LOGOFF:
+		case YAHOO_SERVICE_ISAWAY:
+		case YAHOO_SERVICE_ISBACK:
+		case YAHOO_SERVICE_USERSTAT:
+		case YAHOO_SERVICE_CHATLOGON:
+		case YAHOO_SERVICE_CHATLOGOFF:
+		case YAHOO_SERVICE_GAMELOGON:
+		case YAHOO_SERVICE_GAMELOGOFF:
+			yahoo_parsepacket_status(ctx, pkt, inpkt);
+			break;
+		case YAHOO_SERVICE_IDACT:
+		case YAHOO_SERVICE_IDDEACT:
+			/* nothing needs done, only has main fields */
+			break;
+		case YAHOO_SERVICE_MESSAGE:
+		case YAHOO_SERVICE_SYSMESSAGE:
+		case YAHOO_SERVICE_CHATMSG:
+			yahoo_parsepacket_message(ctx, pkt, inpkt);
+			break;
+		case YAHOO_SERVICE_NEWMAIL:
+		case YAHOO_SERVICE_NEWPERSONALMAIL:
+			yahoo_parsepacket_newmail(ctx, pkt, inpkt);
+			break;
+		case YAHOO_SERVICE_CALENDAR:
+			yahoo_parsepacket_calendar(ctx, pkt, inpkt);
+			break;
+		case YAHOO_SERVICE_CHATINVITE:
+			yahoo_parsepacket_chatinvite(ctx, pkt, inpkt);
+			break;
+		case YAHOO_SERVICE_NEWCONTACT:
+			yahoo_parsepacket_newcontact(ctx, pkt, inpkt);
+			break;
+		case YAHOO_SERVICE_GROUPRENAME:
+			yahoo_parsepacket_grouprename(ctx, pkt, inpkt);
+			break;
+		case YAHOO_SERVICE_CONFINVITE:
+			yahoo_parsepacket_conference_invite(ctx, pkt, inpkt);
+			break;
+		case YAHOO_SERVICE_CONFLOGON:
+		case YAHOO_SERVICE_CONFLOGOFF:
+			yahoo_parsepacket_conference_user(ctx, pkt, inpkt);
+			break;
+		case YAHOO_SERVICE_CONFDECLINE:
+			yahoo_parsepacket_conference_decline(ctx, pkt, inpkt);
+			break;
+		case YAHOO_SERVICE_CONFADDINVITE:
+			yahoo_parsepacket_conference_addinvite(ctx, pkt, inpkt);
+			break;
+		case YAHOO_SERVICE_CONFMSG:
+			yahoo_parsepacket_conference_msg(ctx, pkt, inpkt);
+			break;
+		case YAHOO_SERVICE_PING:
+			yahoo_parsepacket_ping(ctx, pkt, inpkt);
+			break;
+		case YAHOO_SERVICE_FILETRANSFER:
+			yahoo_parsepacket_filetransfer(ctx, pkt, inpkt);
+			break;
+		default:
+			yahoo_dbg_Print("libyahoo",
+				"yahoo_parsepacket: can't parse packet type (%d)\n",
+				pkt->service);
+			break;
+	}
+
+	return pkt;
+}
+
+int yahoo_parsepacket_ping(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
+{
+	char *content;
+
+	/* Make working copy of content */
+	content = inpkt->content;
+
+	pkt->msg = NULL;
+	if (content)
+	{
+		pkt->msg = strdup(content);
+	}
+
+	return 0;
+}
+
+int yahoo_parsepacket_newmail(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
+{
+	char *content;
+	int len;
+
+	/* Make working copy of content */
+	content = inpkt->content;
+	len = strlen(content);
+
+	if (pkt->service == YAHOO_SERVICE_NEWMAIL)
+	{
+		pkt->mail_status = 0;
+		if (len > 0)
+		{
+			pkt->mail_status = atoi(content);
+		}
+	}
+	else if (pkt->service == YAHOO_SERVICE_NEWPERSONALMAIL)
+	{
+		pkt->mail_status = 0;
+		if (len > 0)
+		{
+			pkt->mail_status = atoi(content);
+		}
+	}
+
+	return 0;
+}
+
+int yahoo_parsepacket_grouprename(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
+{
+	char *content;
+	char *tmp, delim[5];
+
+	/* Make working copy of content */
+	content = strdup(inpkt->content);
+
+	/* init elements to all null */
+	pkt->group_old = NULL;
+	pkt->group_new = NULL;
+
+	tmp = NULL;
+	delim[0] = 1;				/* control-a */
+	delim[1] = 0;
+
+	if (content)
+	{
+		tmp = strtok(content, delim);
+	}
+
+	if (tmp)					/* got the conference id */
+	{
+		pkt->group_old = strdup(tmp);
+		tmp = strtok(NULL, delim);
+	}
+
+	if (tmp)					/* conference host */
+	{
+		pkt->group_new = strdup(tmp);
+		tmp = strtok(NULL, delim);
+	}
+
+	FREE(content);
+	return (0);
+}
+
+/*
+
+yahoo_parsepacket_conference_invite()
+
+Packet format:
+   id^host^invited-users^msg^0or1
+
+Parses Arguments:
+   char *conf_id ==   The conference id -- usually of the form name-number,
+                      though it doesn't seem to matter much. ex: jaylubo-123
+   char *conf_host == The person inviting you to conference.
+   char **userlist == Everyone else invited to conference.
+                      Null terminated array of strings.
+   char *msg ==       Invitation message.
+   int conf_type ==   Type of conference ( 0 = text, 1 = voice )
+
+*/
+int yahoo_parsepacket_conference_invite(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
+{
+	char *content;
+	char *tmp = 0;
+	size_t found = 0, len = yahoo_makeint(inpkt->len);
+
+	/* Make working copy of content */
+	content = memdup(inpkt->content, len);
+
+	/* init elements to all null */
+	pkt->conf_id = NULL;
+	pkt->conf_host = NULL;
+	pkt->conf_user = pkt->active_id;
+	pkt->conf_userlist = NULL;
+	pkt->conf_inviter = NULL;
+	pkt->conf_msg = NULL;
+
+	if (content)
+	{
+		tmp = memtok(content, len, "\002", 2, &found);
+	}
+
+	if (tmp)					/* got the conference id */
+	{
+		pkt->conf_id = memdupasstr(tmp, found);
+		tmp = memtok(0, 0, "\002", 2, &found);
+	}
+
+	if (tmp)					/* conference host */
+	{
+		pkt->conf_host = memdupasstr(tmp, found);
+		tmp = memtok(0, 0, "\002", 2, &found);
+	}
+
+	if (tmp)					/* who else is invited */
+	{
+		char *userlist = memdupasstr(tmp, found);
+
+		pkt->conf_userlist = yahoo_list2array(userlist);
+		FREE(userlist);
+		tmp = memtok(0, 0, "\002", 2, &found);
+	}
+
+	if (tmp)					/* msg */
+	{
+		pkt->conf_msg = memdupasstr(tmp, found);
+		tmp = memtok(0, 0, "\002", 2, &found);
+	}
+
+	if (tmp)					/* 0 == text chat 1 == voice chat */
+	{
+		char *conftype = memdupasstr(tmp, found);
+
+		if (0 != conftype)
+			pkt->conf_type = atoi(conftype);
+		FREE(conftype);
+		tmp = memtok(0, 0, "\002", 2, &found);
+	}
+
+	FREE(content);
+	return 0;
+}
+
+/*
+
+yahoo_parsepacket_conference_decline()
+
+Packet format:
+   id^user-who-declined^msg
+
+Parses Arguments:
+   char *conf_id ==   The conference id -- usually of the form name-number,
+                      though it doesn't seem to matter much. ex: jaylubo-123
+   char *conf_user == User who declined.
+   char *msg ==       Reason for declining.
+
+*/
+int yahoo_parsepacket_conference_decline(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
+{
+	char *content;
+	char *tmp, delim[2];
+
+	/* Make working copy of content */
+	content = strdup(inpkt->content);
+
+	/* init elements to all null */
+	pkt->conf_id = NULL;
+	pkt->conf_host = NULL;
+	pkt->conf_user = NULL;
+	pkt->conf_userlist = NULL;
+	pkt->conf_inviter = NULL;
+	pkt->conf_msg = NULL;
+
+	tmp = NULL;
+	delim[0] = 2;				/* control-b */
+	delim[1] = 0;
+
+	if (content)
+	{
+		tmp = strtok(content, delim);
+	}
+
+	if (tmp)					/* got the conference id */
+	{
+		pkt->conf_id = strdup(tmp);
+		tmp = strtok(NULL, delim);
+	}
+	if (tmp)					/* got the user who declined */
+	{
+		pkt->conf_user = strdup(tmp);
+		tmp = strtok(NULL, delim);
+	}
+	if (tmp)					/* msg */
+	{
+		pkt->conf_msg = strdup(tmp);
+		tmp = strtok(NULL, delim);
+	}
+
+	FREE(content);
+	return 0;
+
+}
+
+/*
+
+yahoo_parsepacket_conference_addinvite()
+
+Packet format:
+Msgtype == 1
+   id^inviter^who-else-invited^who-else-in-conf^msg^0or1
+Msgtype == 11
+   id^inviter^invited-user
+
+Parses Arguments:
+   char *conf_id ==   The conference id -- usually of the form name-number,
+                      though it doesn't seem to matter much. ex: jaylubo-123
+   char *conf_inviter == The person inviting you to conference.
+   char **userlist == Everyone else in conference.
+                      Null terminated array of strings.
+   char *msg ==       Invitation message.
+   int conf_type ==   Type of conference ( 0 = text, 1 = voice )
+
+   char *conf_user == User invited to conference (msgtype == 11)
+*/
+int yahoo_parsepacket_conference_addinvite(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
+{
+	char *content = 0, *tmp = 0;
+	size_t found = 0, len = yahoo_makeint(inpkt->len);
+
+	/* Make working copy of content */
+	content = memdup(inpkt->content, len);
+
+	/* init elements to all null */
+	pkt->conf_id = NULL;
+	pkt->conf_host = NULL;
+	pkt->conf_user = NULL;
+	pkt->conf_userlist = NULL;
+	pkt->conf_inviter = NULL;
+	pkt->conf_msg = NULL;
+
+	if (pkt->msgtype == 1)
+	{
+		if (content)
+		{
+			tmp = memtok(content, len, "\002", 2, &found);
+		}
+
+		if (tmp)				/* got the conference id */
+		{
+			pkt->conf_id = memdupasstr(tmp, found);
+			tmp = memtok(0, 0, "\002", 2, &found);
+		}
+		if (tmp)				/* got the inviter */
+		{
+			pkt->conf_inviter = memdupasstr(tmp, found);
+			tmp = memtok(0, 0, "\002", 2, &found);
+		}
+		if (tmp)				/* got who-else-invited */
+		{
+			/* don't use this field, its the same as the next one
+			   so I'm going to use the second field */
+			/* pkt->conf_userlist = yahoo_list2array(tmp); */
+			tmp = memtok(0, 0, "\002", 2, &found);
+		}
+		if (tmp)				/* got the people in conference
+								   not counting the inviter */
+		{
+			char *userlist = memdupasstr(tmp, found);
+
+			pkt->conf_userlist = yahoo_list2array(userlist);
+			FREE(userlist);
+			tmp = memtok(0, 0, "\002", 2, &found);
+		}
+		if (tmp)				/* got the message */
+		{
+			pkt->conf_msg = memdupasstr(tmp, found);
+			tmp = memtok(0, 0, "\002", 2, &found);
+		}
+		if (tmp)				/* 0 at the end */
+		{
+			char *conftype = memdupasstr(tmp, found);
+
+			if (0 != conftype)
+				pkt->conf_type = atoi(conftype);
+			FREE(conftype);
+			/* tmp = memtok (0, 0, "\002", 2, &found); */
+		}
+	}
+	else
+		/* msgid == 11 (someone else is being invited) */
+	{
+		if (content)
+		{
+			tmp = memtok(content, len, "\002", 2, &found);
+		}
+
+		if (tmp)				/* got the conference id */
+		{
+			pkt->conf_id = memdupasstr(tmp, found);
+			tmp = memtok(0, 0, "\002", 2, &found);
+		}
+
+		if (tmp)				/* got the inviter */
+		{
+			pkt->conf_inviter = memdupasstr(tmp, found);
+			tmp = memtok(0, 0, "\002", 2, &found);
+		}
+
+		if (tmp)				/* got the invited-user */
+		{
+			pkt->conf_user = memdupasstr(tmp, found);
+			/* tmp = memtok (0, 0, "\002", 2, &found); */
+		}
+	}
+
+	FREE(content);
+	return 0;
+}
+
+/*
+
+yahoo_parsepacket_conference_msg()
+
+Packet format:
+   id^who-from^msg
+
+Parses Arguments:
+   char *conf_id ==   The conference id -- usually of the form name-number,
+                      though it doesn't seem to matter much. ex: jaylubo-123
+   char *conf_user == User who sent message.
+   char *msg ==       Message.
+
+*/
+int yahoo_parsepacket_conference_msg(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
+{
+	char *content;
+	char *tmp, delim[5];
+
+	/* Make working copy of content */
+	content = strdup(inpkt->content);
+
+	/* init elements to all null */
+	pkt->conf_id = NULL;
+	pkt->conf_host = NULL;
+	pkt->conf_user = NULL;
+	pkt->conf_userlist = NULL;
+	pkt->conf_inviter = NULL;
+	pkt->conf_msg = NULL;
+
+	tmp = NULL;
+	delim[0] = 2;				/* control-b */
+	delim[1] = 0;
+
+	/* parse error messages first */
+	if (pkt->msgtype == YAHOO_MSGTYPE_ERROR)
+	{
+		FREE(content);
+		return 0;
+	}
+
+	if (content)
+	{
+		tmp = strtok(content, delim);
+	}
+
+	if (tmp)					/* got the conference id */
+	{
+		pkt->conf_id = strdup(tmp);
+		tmp = strtok(NULL, delim);
+	}
+
+	if (tmp)					/* conference user */
+	{
+		pkt->conf_user = strdup(tmp);
+		tmp = strtok(NULL, delim);
+	}
+
+	if (tmp)					/* msg */
+	{
+		pkt->conf_msg = strdup(tmp);
+		tmp = strtok(NULL, delim);
+	}
+
+	FREE(content);
+	return 0;
+}
+
+/*
+
+yahoo_parsepacket_conference_user()
+   (User logged on/off to conference)
+Packet format:
+   id^user_who_logged_on/off
+
+Parses Arguments:
+   char *conf_id ==   The conference id -- usually of the form name-number,
+                      though it doesn't seem to matter much. ex: jaylubo-123
+   char *conf_user == User who logged on to conference.
+
+*/
+int yahoo_parsepacket_conference_user(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
+{
+	char *content;
+	char *tmp, delim[5];
+
+	/* Make working copy of content */
+	content = strdup(inpkt->content);
+
+	/* init elements to all null */
+	pkt->conf_id = NULL;
+	pkt->conf_host = NULL;
+	pkt->conf_user = NULL;
+	pkt->conf_userlist = NULL;
+	pkt->conf_inviter = NULL;
+	pkt->conf_msg = NULL;
+
+	tmp = NULL;
+	delim[0] = 2;				/* control-b */
+	delim[1] = 0;
+
+	if (content)
+	{
+		tmp = strtok(content, delim);
+	}
+
+	if (tmp)					/* got the conference id */
+	{
+		pkt->conf_id = strdup(tmp);
+		tmp = strtok(NULL, delim);
+	}
+
+	if (tmp)					/* conference user */
+	{
+		pkt->conf_user = strdup(tmp);
+		tmp = strtok(NULL, delim);
+	}
+
+	FREE(content);
+	return 0;
+}
+
+int yahoo_parsepacket_filetransfer(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
+{
+	char *content;
+	char *tmp[5];
+	int i, j, section;
+
+	/* Make working copy of content */
+	content = strdup(inpkt->content);
+
+	/* init elements to all null */
+	pkt->file_from = NULL;
+	pkt->file_flag = NULL;
+	pkt->file_url = NULL;
+	pkt->file_expires = 0;
+	pkt->file_description = NULL;
+
+	/* overkill allocation, but simple since only temporary use */
+	tmp[0] = strdup(content);
+	tmp[1] = strdup(content);
+	tmp[2] = strdup(content);
+	tmp[3] = strdup(content);
+	tmp[4] = strdup(content);
+
+	/* raw data format: from,flag,url,timestamp,description */
+
+	i = 0;
+	j = 0;
+	section = 0;
+	tmp[0][0] = 0;
+	tmp[1][0] = 0;
+	tmp[2][0] = 0;
+	tmp[3][0] = 0;
+	tmp[4][0] = 0;
+
+	while (i < strlen(content))
+	{
+		char ch = content[i];
+
+		if (ch == ',' && section < 4)
+		{
+			j = 0;
+			section++;
+		}
+		else
+		{
+			tmp[section][j++] = ch;
+			tmp[section][j] = 0;
+		}
+		i++;
+	}
+
+	/* do stuff with extracted parts */
+	pkt->file_from = strdup(tmp[0]);
+	pkt->file_flag = strdup(tmp[1]);
+	pkt->file_url = strdup(tmp[2]);
+	pkt->file_expires = atoi(tmp[3]);
+	pkt->file_description = strdup(tmp[4]);
+
+	/* free working variables */
+	FREE(tmp[0]);
+	FREE(tmp[1]);
+	FREE(tmp[2]);
+	FREE(tmp[3]);
+	FREE(tmp[4]);
+	FREE(content);
+	return 0;
+}
+
+int yahoo_parsepacket_calendar(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
+{
+	char *content;
+	char *tmp, delim[5];
+
+	/* Make working copy of content */
+	content = strdup(inpkt->content);
+
+	/* init elements to all null */
+	pkt->cal_url = NULL;
+	pkt->cal_timestamp = NULL;
+	pkt->cal_type = 0;
+	pkt->cal_title = NULL;
+	pkt->cal_description = NULL;
+
+	tmp = NULL;
+	delim[0] = 2;				/* control-b */
+	delim[1] = 0;
+
+	if (content)
+	{
+		tmp = strtok(content, delim);
+	}
+
+	if (tmp)					/* got the url */
+	{
+		pkt->cal_url = strdup(tmp);
+		tmp = strtok(NULL, delim);
+
+/*
+   v= is not the type code
+   i= doesn't look like it either
+   tmp2 = strstr(pkt->cal_url, "v=");
+   if ( tmp2 )
+   {
+   pkt->cal_type = atoi(tmp2);
+   }
+ */
+
+	}
+
+	if (tmp)					/* unknown (type code?) */
+	{
+/* appears this isn't it either, I don't see where it is */
+/*      pkt->cal_type = atoi(tmp);  */
+		tmp = strtok(NULL, "\r\n");
+	}
+
+	if (tmp)					/* timestamp */
+	{
+		pkt->cal_timestamp = strdup(tmp);
+		tmp = strtok(NULL, "\r\n");
+	}
+
+	if (tmp)					/* title */
+	{
+		pkt->cal_title = strdup(tmp);
+		tmp = strtok(NULL, delim);	/* use delim since it won't occur again */
+	}
+
+	if (tmp)
+	{
+		pkt->cal_description = strdup(tmp);
+	}
+
+	FREE(content);
+	return 0;
+}
+
+int yahoo_parsepacket_chatinvite(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
+{
+	char *content;
+	int len;
+
+	/* Make working copy of content */
+	content = strdup(inpkt->content);
+	len = strlen(content);
+
+	/* do special parsing for invite later on */
+	pkt->chat_invite_content = strdup(content);
+
+	return 0;
+}
+
+int yahoo_parsepacket_newcontact(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
+{
+	char *content;
+	int len;
+
+	/* Make working copy of content */
+	content = strdup(inpkt->content);
+	len = strlen(content);
+
+	/* cheat for now, say if first digit is number */
+	if (len > 0)
+	{
+		if (isdigit((int) content[0]))
+		{
+			return yahoo_parsepacket_status(ctx, pkt, inpkt);
+		}
+		else
+		{
+			return yahoo_parsepacket_message(ctx, pkt, inpkt);
+		}
+	}
+
+	return 0;
+}
+
+int yahoo_parsepacket_status(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
+{
+	char *content;
+	char *tmpc;
+	char *tmp1;
+	int i;
+	int len;
+	int index;
+	int realcount;
+
+	/* Make working copy of content */
+	content = strdup(inpkt->content);
+	len = strlen(content);
+
+	/* Pull off the flag from the initial part of the content */
+	/* this flag indicates the number of buddy that're online */
+	pkt->flag = 0;
+	tmpc = content;
+	while (tmpc[0] && isdigit((int) tmpc[0]))
+	{
+		pkt->flag = pkt->flag * 10 + (content[0] - '0');
+		tmpc++;
+	}
+	if (tmpc[0] && tmpc[0] == ',')
+	{
+		tmpc++;
+	}
+
+	/*
+	   We're receiving either this:
+	   2,buddy1(0,728EE9FB,0,1,0,0),buddy2(0,7AC00000,0,1,0,0)
+	   or this:
+	   buddy1(0,728EE9FB,0,1,0,0)
+	   hence:
+	 */
+
+	if (pkt->flag == 0)
+	{
+		pkt->idstatus_count = 1;
+	}
+	else
+	{
+		pkt->idstatus_count = pkt->flag;
+	}
+
+	/* print an error if I get the was not AWAY */
+	if (strstr(tmpc, "was not AWAY"))
+	{
+		pkt->idstatus_count = 0;
+		yahoo_dbg_Print("libyahoo", "yahoo_parsepacket_status: "
+			"got a 'was not AWAY' message\n");
+	}
+
+	if (pkt->idstatus_count == 0)
+	{
+		/* No entries, so no array needed */
+		pkt->idstatus = NULL;
+	}
+	else
+	{
+		/* Allocate the array */
+		pkt->idstatus = (struct yahoo_idstatus **)
+			calloc(sizeof(struct yahoo_idstatus), pkt->idstatus_count);
+
+		for (i = 0; i < pkt->idstatus_count; i++)
+		{
+			pkt->idstatus[i] = (struct yahoo_idstatus *)
+
+				calloc(1, sizeof(struct yahoo_idstatus));
+		}
+	}
+
+	index = 0;
+	tmp1 = NULL;
+	realcount = 0;
+	while (tmpc && tmpc[0] && pkt->idstatus)
+	{
+		struct yahoo_idstatus *tmpid;
+
+		/* Get pointer to allocated structure to hold status data */
+		tmpid = pkt->idstatus[index++];
+		if (!tmpid)
+		{
+			/* shortcut, we know there can't be any more status entries
+			   at this point */
+			/* yahoo_dbg_Print("status", "null tmpid"); */
+			break;
+		}
+
+		/* YPNS2.0 nick(status,msg,connection_id,UNK,in_pager,in_chat,in_game) */
+		/* tnneul(99,test,message^A,6AD68325,0,1,0,0) */
+		/*         0 1               2       3 4 5 6 */
+
+		/* YPNS1.0 nick(status,connection_id,UNK,in_pager,in_chat,in_game) */
+		/* nneul(0,7081F531,0,1,0,0) */
+		/*       0 2        3 4 5 6 */
+
+		/* rewrite this whole section in a less ugly fashion */
+		/* first pull off the id */
+
+		/* YUCK - YPNS2.0 has variable format status records, if type is 99,
+		   it has 7 fields, second is msg */
+
+#if 0
+		yahoo_dbg_Print("status", "whole string = '%s'\n",
+			yahoo_dbg_NullCheck(tmpc));
+#endif
+
+		if (tmp1)
+		{
+			tmp1 = strtok(NULL, "(");
+		}
+		else
+		{
+			tmp1 = strtok(tmpc, "(");
+		}
+		if (tmp1 && tmp1[0] == ',')
+		{
+			tmp1++;
+		}
+
+		if (tmp1)
+		{
+			tmpid->id = strdup(tmp1);
+			realcount++;
+
+			for (i = 0; i <= 6 && tmp1; i++)
+			{
+#if 0
+				yahoo_dbg_Print("status", "i==%d\n", i);
+#endif
+
+				if (i == 6)		/* end of status area */
+				{
+					tmp1 = strtok(NULL, "),");
+				}
+				else if (i == 1)
+				{
+					char delim[3];
+
+					if (tmpid->status == YAHOO_STATUS_CUSTOM)
+					{
+						delim[0] = 1;
+						delim[1] = ',';
+						delim[1] = 0;
+						tmp1 = strtok(NULL, delim);
+					}
+					else
+					{
+						i = 2;
+						tmp1 = strtok(NULL, ",");
+					}
+				}
+				else
+				{
+
+					tmp1 = strtok(NULL, ",");
+				}
+
+				/* then pull off the particular element of the list */
+				if (tmp1)
+				{
+					switch (i)
+					{
+						case 0:	/* status */
+							tmpid->status = atoi(tmp1);
+							break;
+						case 1:	/* msg */
+							if (tmpid->status == YAHOO_STATUS_CUSTOM)
+							{
+								tmpid->status_msg = strdup(tmp1);
+							}
+							break;
+						case 2:	/* session id */
+							tmpid->connection_id = strdup(tmp1);
+							break;
+						case 3:	/* dunno what this is */
+							break;
+						case 4:
+							tmpid->in_pager = atoi(tmp1);
+							break;
+						case 5:
+							tmpid->in_chat = atoi(tmp1);
+							break;
+						case 6:
+							tmpid->in_game = atoi(tmp1);
+							break;
+					}
+				}
+			}
+		}
+	}
+
+	for (i = realcount; i <= pkt->idstatus_count; i++)
+	{
+		if (pkt->idstatus && pkt->idstatus[i])
+		{
+			FREE(pkt->idstatus[i]);
+		}
+	}
+	pkt->idstatus_count = realcount;
+
+	/* Free working copy of content */
+	FREE(content);
+
+	/* Return ok for success */
+	return (0);
+}
+
+int yahoo_parsepacket_message(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
+{
+	char *content;
+	char *tmp_id;
+	int i, j, section;
+
+	if (pkt->msgtype == YAHOO_MSGTYPE_OFFLINE)
+	{
+		return yahoo_parsepacket_message_offline(ctx, pkt, inpkt);
+	}
+
+	/* Make working copy of content */
+	content = strdup(inpkt->content);
+	tmp_id = strdup(content);
+
+	/* initialize */
+	pkt->msg_status = 0;
+
+	/* possible message content formats: */
+/*     userid(#) *//* msgtype == YAHOO_MSGTYPE_STATUS */
+	/*     userid,,msg */
+
+	/* this needed butchered */
+	/* YAHOO_MSGTYPE_OFFLINE */
+	/* 6,6,tnneul,nneul,Tue Mar  7 12:14:50 2000,test offline msg^A */
+
+	i = 0;
+	j = 0;
+	section = 0;
+	tmp_id[0] = 0;
+	while (i < strlen(content))
+	{
+		char ch = content[i];
+
+		if (section == 0)		/* parsing userid */
+		{
+			if (ch == ',')
+			{
+				j = 0;
+				section = 1;
+			}
+			else if (ch == '(')
+			{
+				j = 0;
+				section = 2;
+			}
+			else
+			{
+				tmp_id[j++] = ch;
+				tmp_id[j] = 0;
+			}
+		}
+		else if (section == 1)	/* parsing flag */
+		{
+			if (ch == ',')
+			{
+				j = 0;
+				section = 3;
+			}
+		}
+		else if (section == 2)	/* parsing status */
+		{
+			if (ch == ')')
+			{
+				j = 0;
+				section = 3;
+			}
+			else
+			{
+				if (isdigit((int) ch))
+				{
+					pkt->msg_status *= 10;
+					pkt->msg_status += ch - '0';
+				}
+			}
+		}
+		else
+		{
+			pkt->msg = strdup(&content[i]);
+			break;
+		}
+
+		i++;
+	}
+
+	/* do stuff with extracted parts */
+	pkt->msg_id = strdup(tmp_id);
+
+	/* handle empty message case */
+	/* don't pass a message if it's just a status update */
+	if (!pkt->msg && pkt->msgtype != YAHOO_MSGTYPE_STATUS)
+	{
+		pkt->msg = strdup("");
+	}
+
+	/* free working variables */
+	FREE(tmp_id);
+	FREE(content);
+
+	/* Return ok for success */
+	return (0);
+}
+
+/* This parses a special format offline message, and is only currently
+called from yahoo_parsepacket_message. */
+int yahoo_parsepacket_message_offline(struct yahoo_context *ctx,
+	struct yahoo_packet *pkt, struct yahoo_rawpacket *inpkt)
+{
+	char *content;
+	char *to_id;
+	char *from_id;
+	char *timestamp;
+	int i, j, section;
+
+	/* Make working copy of content */
+	content = strdup(inpkt->content);
+	to_id = strdup(content);
+	from_id = strdup(content);
+	timestamp = strdup(content);
+
+	/* initialize */
+	pkt->msg_status = 0;
+
+	/* 6,6,tnneul,nneul,Tue Mar  7 12:14:50 2000,test offline msg^A */
+	/* sec0,sec1,sec2=to,sec3=from,sec4=tstamp,sec5=msg */
+
+	i = 0;
+	j = 0;
+	section = 0;
+	to_id[0] = 0;
+	from_id[0] = 0;
+	timestamp[0] = 0;
+
+	while (i < strlen(content))
+	{
+		char ch = content[i];
+
+		if (section == 0)		/* parsing first unknown number */
+		{
+			if (ch == ',')
+			{
+				j = 0;
+				section = 1;
+			}
+		}
+		else if (section == 1)	/* parsing second unknown number */
+		{
+			if (ch == ',')
+			{
+				j = 0;
+				section = 2;
+			}
+		}
+		else if (section == 2)	/* parsing to-id */
+		{
+			if (ch == ',')
+			{
+				j = 0;
+				section = 3;
+			}
+			else
+			{
+				to_id[j++] = ch;
+				to_id[j] = 0;
+			}
+		}
+		else if (section == 3)	/* parsing from-id */
+		{
+			if (ch == ',')
+			{
+				j = 0;
+				section = 4;
+			}
+			else
+			{
+				from_id[j++] = ch;
+				from_id[j] = 0;
+			}
+		}
+		else if (section == 4)	/* parsing timestamp */
+		{
+			if (ch == ',')
+			{
+				j = 0;
+				section = 5;
+			}
+			else
+			{
+				timestamp[j++] = ch;
+				timestamp[j] = 0;
+			}
+		}
+		else
+		{
+			pkt->msg = strdup(&content[i]);
+			break;
+		}
+
+		i++;
+	}
+
+	/* do stuff with extracted parts */
+	pkt->msg_id = strdup(from_id);
+	pkt->msg_timestamp = strdup(timestamp);
+	if (pkt->active_id)
+	{
+		FREE(pkt->active_id);
+		pkt->active_id = strdup(to_id);
+	}
+
+	/* free working variables */
+	FREE(timestamp);
+	FREE(from_id);
+	FREE(to_id) FREE(content);
+
+	/* Return ok for success */
+	return (0);
+}
+
+int yahoo_getdata(struct yahoo_context *ctx)
+{
+	char buf[1000];
+	int res;
+
+	/* This is a http mode connection, so just send a ping to get any
+	   new data from the server. */
+	if (ctx->connect_mode == YAHOO_CONNECT_HTTP ||
+		ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
+	{
+		yahoo_sendcmd(ctx, YAHOO_SERVICE_PING, ctx->user, "", 0);
+		return (1);
+	}
+
+	/* this assumes that data is ready */
+	/* Read from the connection to the server and get any new data */
+	res = read(ctx->sockfd, buf, 1000);
+	if (res == -1)
+	{
+		yahoo_dbg_Print("io",
+			"yahoo_getdata: error reading data from server\n");
+		return (0);
+	}
+	if (res > 0)
+	{
+		yahoo_addtobuffer(ctx, buf, res);
+		yahoo_dbg_Print("io", "[libyahoo] yahoo_getdata: read (%d) bytes\n",
+			res);
+		return 1;
+	}
+	else if (res == 0)
+	{
+		yahoo_dbg_Print("io",
+			"[libyahoo] yahoo_getdata: got zero length read\n", res);
+		return 0;
+	}
+
+	return (1);
+}
+
+struct yahoo_rawpacket *yahoo_getpacket(struct yahoo_context *ctx)
+{
+	struct yahoo_rawpacket *pkt;
+	struct yahoo_rawpacket *retpkt;
+	int *buflen = &ctx->io_buf_curlen;
+	char *buffer = ctx->io_buf;
+	unsigned int contentlen;
+
+	/* If buffer doesn't start with YHOO, skip bytes until it
+	   does. This is to protect against possible packet alignment
+	   errors if I size something wrong at any time. */
+
+	while ((*buflen >= 4) && (memcmp(buffer, "YHOO", 4)))
+	{
+/* making quiet for now so I don't have to work too hard on the HTTP support */
+#if 0
+		printf("\nskipped buffer byte (%d)\n", buffer[0]);
+#endif
+		memmove(buffer, buffer + 1, *buflen - 1);
+		*buflen = *buflen - 1;
+	}
+
+	/* Don't do anything if the buffer doesn't have at least a full
+	   header */
+	if (*buflen < YAHOO_PACKET_HEADER_SIZE)
+	{
+// printf("returning null cause buffer is too small\n");
+		return NULL;
+	}
+
+/* print out the beginning of the buffer */
+#if 0
+	printf("Buffer (buflen = %d):\n", *buflen);
+	for (i = 0; i < *buflen; i++)
+	{
+		if ((i) % 10 == 0)
+		{
+			printf("\n%.4d: ", i);
+		}
+		if (isprint(buffer[i]))
+		{
+			printf("%-3d %c  ", buffer[i], buffer[i]);
+		}
+		else
+		{
+			printf("%-3d    ", buffer[i]);
+		}
+	}
+	printf("\n");
+#endif
+	/* Make pkt point to buffer for ease of use */
+	pkt = (struct yahoo_rawpacket *) buffer;
+
+	/* Determine the content size specified by the header */
+	contentlen = yahoo_makeint(pkt->len) - YAHOO_PACKET_HEADER_SIZE;
+// printf("contentlen = %d\n", contentlen);
+
+	/* Don't continue if buffer doesn't have full content in it */
+	if (*buflen < (YAHOO_PACKET_HEADER_SIZE + contentlen))
+	{
+// printf("buffer not big enough for contentlen\n");
+		return NULL;
+	}
+
+	/* Copy this packet */
+	retpkt =
+		(struct yahoo_rawpacket *) malloc(YAHOO_PACKET_HEADER_SIZE +
+		contentlen);
+	memcpy(retpkt, buffer, YAHOO_PACKET_HEADER_SIZE + contentlen);
+
+	/* Shift the buffer */
+	memmove(buffer, buffer + YAHOO_PACKET_HEADER_SIZE + contentlen,
+		*buflen - YAHOO_PACKET_HEADER_SIZE - contentlen);
+
+	/* Adjust the buffer length */
+	*buflen -= (YAHOO_PACKET_HEADER_SIZE + contentlen);
+
+	/* Return the packet */
+	return retpkt;
+}
+
+int yahoo_isbuddy(struct yahoo_context *ctx, const char *id)
+{
+	int i;
+	char *buddy = NULL;
+
+	if (!id || !ctx || !ctx->buddies)
+	{
+		return FALSE;
+	}
+
+	for (i = 0; ctx->buddies[i]; i++)
+	{
+		buddy = (ctx->buddies[i])->id;
+		if (!strcasecmp(id, buddy))
+		{
+			return TRUE;
+		}
+	}
+
+	return FALSE;
+}
+
+static void yahoo_free_address (struct yahoo_address *add)
+{
+	yahoo_dbg_Print("addressbook",
+		"[libyahoo] yahoo_free_address: record at address 0x%08p for user %s (%s %s) being free'd\n",
+		add, add->id, add->firstname, add->lastname);
+
+	FREE (add->firstname);
+	FREE (add->lastname);
+	FREE (add->emailnickname);
+	FREE (add->email);
+	FREE (add->workphone);
+	FREE (add->homephone);
+}
+
+void yahoo_freeaddressbook(struct yahoo_context *ctx)
+{
+	unsigned int count = ctx->address_count;
+	struct yahoo_address *add_p = ctx->addresses;
+
+	if (NULL == ctx || NULL == ctx->addresses)
+		return;
+
+	while (count-- > 0)
+	{
+		yahoo_free_address (add_p++);
+	}
+
+	ctx->address_count = 0;
+	FREE (ctx->addresses);
+}
+
+static void yahoo_data_to_addressbook (char *block, struct yahoo_context *ctx)
+{
+	char *token = NULL;
+	int record = 0;
+	struct yahoo_address *add = NULL;
+
+	if (NULL == block || NULL == ctx)
+		return;
+
+	yahoo_freeaddressbook (ctx);
+
+	add = ctx->addresses = calloc (ctx->address_count, sizeof (struct yahoo_address));
+
+	/*
+	 Okay!
+	 At this point we have a char * (block) that has \012 delimited records
+	 Each record (as a string when retreived with strtok) follows the format:
+	<ID>:<FIRSTNAME>\011<LASTNAME>\011<EMAILNICKNAME>\011<EMAIL>\011<HOMEPHONE>\011<WORKPHONE>\011[01]\011<ENTRYID>\000
+	 */
+
+	token = strtok (block, "\012");
+	while (NULL != token)
+	{
+		/*
+		 Here we must use memtok because we'll get some repeated tokens!!!!!
+		 */
+		char *field = NULL;
+		size_t token_len = 0, found = 0;
+
+		++record;
+		token_len = strlen (token);
+
+		field = memtok(token, token_len, ":", 1, &found);
+
+		if (NULL != field)
+		{
+			add->id = memdupasstr(field, found);
+			field = memtok(0, 0, "\011", 1, &found);
+		}
+
+		if (NULL != field)
+		{
+			add->firstname = memdupasstr(field, found);
+			field = memtok(0, 0, "\011", 1, &found);
+		}
+
+		if (NULL != field)
+		{
+			add->lastname = memdupasstr(field, found);
+			field = memtok(0, 0, "\011", 1, &found);
+		}
+
+		if (NULL != field)
+		{
+			add->emailnickname = memdupasstr(field, found);
+			field = memtok(0, 0, "\011", 1, &found);
+		}
+
+		if (NULL != field)
+		{
+			add->email = memdupasstr(field, found);
+			field = memtok(0, 0, "\011", 1, &found);
+		}
+
+		if (NULL != field)
+		{
+			add->homephone = memdupasstr(field, found);
+			field = memtok(0, 0, "\011", 1, &found);
+		}
+
+		if (NULL != field)
+		{
+			add->workphone = memdupasstr(field, found);
+			field = memtok(0, 0, "\011", 1, &found);
+		}
+
+		if (NULL != field)
+		{
+			add->primary_phone = (*field == '0' ? home : work);
+			field = memtok(0, 0, "", 1, &found);
+		}
+
+		if (NULL != field)
+		{
+			char *entryid = memdupasstr(field, found);
+			if (NULL != entryid)
+			{
+				add->entryid = atoi (entryid);
+				FREE (entryid);
+			}
+		}
+
+		yahoo_dbg_Print("addressbook",
+			"[libyahoo] yahoo_fetchaddressbook: record #%d is for user %s (%s %s)\n",
+			record, add->id, add->firstname, add->lastname);
+
+		++add;
+
+		token = strtok (NULL, "\012");
+	}
+}
+
+/* retreive the details of the friends in your address book that have a Yahoo! id listed */
+int yahoo_fetchaddressbook(struct yahoo_context *ctx)
+{
+	char buffer[5000];
+	int servfd;
+	int res;
+	int copied = 0, size = 5000;
+	char *address = NULL, *copy = NULL;
+
+	if (!ctx)
+	{
+		return 0;
+	}
+
+	yahoo_dbg_Print("addressbook",
+		"[libyahoo] yahoo_fetchaddressbook: starting\n");
+
+	/* Check for cached addresses */
+	if (ctx->addresses)
+	{
+		yahoo_freeaddressbook(ctx);
+	}
+
+	if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
+	{
+		servfd = yahoo_socket_connect(ctx, ctx->proxy_host, ctx->proxy_port);
+	}
+	else
+	{
+		servfd = yahoo_socket_connect(ctx, YAHOO_ADDRESS_HOST, YAHOO_ADDRESS_PORT);
+	}
+
+	if (!servfd)
+	{
+		printf("[libyahoo] failed to connect to address book server.\n");
+		return (0);
+	}
+
+	strcpy(buffer, "GET ");
+	if (ctx->connect_mode == YAHOO_CONNECT_HTTPPROXY)
+	{
+		strcat(buffer, YAHOO_ADDRESS_HOST);
+	}
+	strcat(buffer, "/yab/uk/yab?v=PG&A=s");
+	strcat(buffer, " HTTP/1.0\r\n");
+	strcat(buffer, "User-Agent: " YAHOO_USER_AGENT "\r\n");
+	strcat(buffer, "Host: " YAHOO_AUTH_HOST "\r\n");
+	strcat(buffer, "Cookie: ");
+	strcat(buffer, ctx->cookie);
+	strcat(buffer, "\r\n");
+	strcat(buffer, "\r\n");
+
+	write(servfd, buffer, strlen(buffer));
+
+	yahoo_dbg_Print("addressbook",
+		"[libyahoo] yahoo_fetchaddressbook: writing buffer '%s'\n", buffer);
+
+	while ((res = yahoo_tcp_readline(buffer, 5000, servfd)) > 0)
+	{
+		if ('\012' == buffer[0])
+			continue;
+
+		if (0 == strncmp (buffer, "1\011", 2))
+		{
+			yahoo_dbg_Print("addressbook",
+				"[libyahoo] yahoo_fetchaddressbook: found first line\n");
+			if (3 == res)
+			{
+				yahoo_dbg_Print("addressbook",
+					"[libyahoo] yahoo_fetchaddressbook: however there's been a problem\n");
+				break;
+			}
+
+			address = &buffer[2];
+		}
+		else if (NULL != address)
+		{
+			address = &buffer[0];
+		}
+
+		if (NULL != address)
+		{
+			if (NULL == copy)
+			{
+				copy = malloc (size);
+				memset (copy, 0, size);
+			}
+
+			if ((copied + res) > size)
+			{
+				char *newcopy = NULL;
+
+				yahoo_dbg_Print("addressbook",
+					"[libyahoo] yahoo_fetchaddressbook: resizing buffer from %d bytes to %d bytes\n", size, size * 2);
+				size *= 2;
+				newcopy = malloc (size);
+				memset (newcopy, 0, size);
+				memcpy (newcopy, copy, copied);
+				free (copy);
+				copy = newcopy;
+			}
+
+			copied += res;
+			strcat (copy, address);
+			++ctx->address_count;
+		}
+	}
+
+	yahoo_data_to_addressbook (copy, ctx);
+	FREE (copy);
+
+	yahoo_dbg_Print("addressbook",
+		"[libyahoo] yahoo_fetchaddressbook: closing server connection\n");
+	close(servfd);
+	servfd = 0;
+	yahoo_dbg_Print("addressbook",
+		"[libyahoo] yahoo_fetchaddressbook: closed server connection\n");
+
+	yahoo_dbg_Print("addressbook", "[libyahoo] yahoo_fetchaddressbook: done (%d addresses retreived)\n", ctx->address_count);
+
+	return ctx->address_count;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/yay/libyahoo.h	Fri Nov 03 10:03:53 2000 +0000
@@ -0,0 +1,284 @@
+#ifndef LIBYAHOO_H
+#define LIBYAHOO_H
+
+/* Service constants */
+#define YAHOO_SERVICE_LOGON		1
+#define YAHOO_SERVICE_LOGOFF		2
+#define YAHOO_SERVICE_ISAWAY		3
+#define YAHOO_SERVICE_ISBACK		4
+#define YAHOO_SERVICE_IDLE		5
+#define YAHOO_SERVICE_MESSAGE		6
+#define YAHOO_SERVICE_IDACT		7
+#define YAHOO_SERVICE_IDDEACT		8
+#define YAHOO_SERVICE_MAILSTAT	9
+#define YAHOO_SERVICE_USERSTAT	10
+#define YAHOO_SERVICE_NEWMAIL		11
+#define YAHOO_SERVICE_CHATINVITE	12
+#define YAHOO_SERVICE_CALENDAR	13
+#define YAHOO_SERVICE_NEWPERSONALMAIL		14
+#define YAHOO_SERVICE_NEWCONTACT	15
+#define YAHOO_SERVICE_ADDIDENT	16
+#define YAHOO_SERVICE_ADDIGNORE	17
+#define YAHOO_SERVICE_PING		18
+#define YAHOO_SERVICE_GROUPRENAME	19
+#define YAHOO_SERVICE_SYSMESSAGE	20
+#define YAHOO_SERVICE_PASSTHROUGH2	22
+#define YAHOO_SERVICE_CONFINVITE 24
+#define YAHOO_SERVICE_CONFLOGON	25
+#define YAHOO_SERVICE_CONFDECLINE 26
+#define YAHOO_SERVICE_CONFLOGOFF		27
+#define YAHOO_SERVICE_CONFADDINVITE 28
+#define YAHOO_SERVICE_CONFMSG 29
+#define YAHOO_SERVICE_CHATLOGON	30
+#define YAHOO_SERVICE_CHATLOGOFF	31
+#define YAHOO_SERVICE_CHATMSG 32
+#define YAHOO_SERVICE_GAMELOGON 40
+#define YAHOO_SERVICE_GAMELOGOFF 41
+#define YAHOO_SERVICE_FILETRANSFER 70
+
+/* Yahoo style/color directives */
+#define YAHOO_COLOR_BLACK "\033[30m"
+#define YAHOO_COLOR_BLUE "\033[31m"
+#define YAHOO_COLOR_LIGHTBLUE "\033[32m"
+#define YAHOO_COLOR_GRAY "\033[33m"
+#define YAHOO_COLOR_GREEN "\033[34m"
+#define YAHOO_COLOR_PINK "\033[35m"
+#define YAHOO_COLOR_PURPLE "\033[36m"
+#define YAHOO_COLOR_ORANGE "\033[37m"
+#define YAHOO_COLOR_RED "\033[38m"
+#define YAHOO_COLOR_OLIVE "\033[39m"
+#define YAHOO_STYLE_ITALICON "\033[2m"
+#define YAHOO_STYLE_ITALICOFF "\033[x2m"
+#define YAHOO_STYLE_BOLDON "\033[1m"
+#define YAHOO_STYLE_BOLDOFF "\033[x1m"
+#define YAHOO_STYLE_UNDERLINEON "\033[4m"
+#define YAHOO_STYLE_UNDERLINEOFF "\033[x4m"
+#define YAHOO_STYLE_URLON "\033[lm"
+#define YAHOO_STYLE_URLOFF "\033[xlm"
+
+/* Message flags */
+#define YAHOO_MSGTYPE_ERROR 		-1	/* 0xFFFFFFFF */
+#define YAHOO_MSGTYPE_NONE 		0	/* ok */
+#define YAHOO_MSGTYPE_NORMAL 		1	/* notify */
+#define YAHOO_MSGTYPE_BOUNCE 		2	/* not available */
+#define YAHOO_MSGTYPE_STATUS	 	4	/* user away */
+#define YAHOO_MSGTYPE_OFFLINE 		5
+#define YAHOO_MSGTYPE_INVISIBLE 	12
+
+#define YAHOO_MSGTYPE_KNOWN_USER 	1515563606	/* 0x5A55AA56 */
+#define YAHOO_MSGTYPE_UNKNOWN_USER 	1515563605	/* 0x5A55AA55 */
+
+#define YAHOO_CONF_LEVEL_0		0
+
+/* Structure definitions */
+
+enum phone { home = 0, work };
+
+struct yahoo_address
+{
+	char *id;
+	char *firstname;
+	char *lastname;
+	char *emailnickname;
+	char *email;
+	char *workphone;
+	char *homephone;
+	enum phone primary_phone;
+	unsigned int entryid;
+};
+
+struct yahoo_context
+{
+	/* Input parameters from calling application */
+	char *user;
+	char *password;
+	int connect_mode;			/* connection mode */
+	int proxy_port;
+	char *proxy_host;
+
+	/* Semi-public */
+	int sockfd;					/* pager server socket */
+
+	/* IO buffer parameters */
+	char *io_buf;				/* Buffer for storing incoming packets */
+	int io_buf_curlen;
+	int io_buf_maxlen;
+
+	/* Cookie data */
+	char *cookie;
+	char *login_cookie;
+
+	/* Buddy list parameters */
+	struct yahoo_buddy **buddies;	/* list of groups and buddies */
+	char **identities;			/* list of identities */
+	char *login_id;				/* what id should be specified as the primary id */
+	int mail;					/* I think this indicates if user has a yahoo mail id */
+
+	/* Temporary to hold the magic id for outbound packets */
+	unsigned int magic_id;
+	unsigned int connection_id;
+	unsigned int address_count;
+	struct yahoo_address *addresses;
+};
+
+struct yahoo_options
+{
+	int connect_mode;
+
+	char *proxy_host;
+	int proxy_port;
+};
+
+struct yahoo_rawpacket
+{
+	char version[8];			/* 7 chars and trailing null */
+	unsigned char len[4];		/* length - little endian */
+	unsigned char service[4];	/* service - little endian */
+
+/* 3 X 4bytes - host, port, ip_address */
+/* not sure what diff is between host and ip addr */
+	unsigned char connection_id[4];	/* connection number - little endian */
+	unsigned char magic_id[4];	/* magic number used for http session */
+	unsigned char unknown1[4];
+
+	unsigned char msgtype[4];
+	char nick1[36];
+	char nick2[36];
+	char content[1];			/* was zero, had problems with aix xlc */
+};
+
+/*
+ * Structure for returning the status/flags/etc. of a particular id
+ */
+struct yahoo_idstatus
+{
+	char *id;
+	int status;
+	char *status_msg;
+	char *connection_id;
+	int in_pager;
+	int in_chat;
+	int in_game;				/* not sure */
+};
+
+/*
+ * Structure for returning a buddy entry
+ */
+struct yahoo_buddy
+{
+	char *group;				/* member of what group */
+	char *id;					/* the buddy's id */
+};
+
+/*
+ * Generic packet type for returning from the parse routine
+ * The fields in this packet are not all used and are defined
+ * so that a single type of packet can be returned from the parse routine
+ */
+
+struct yahoo_packet
+{
+	/* Common info */
+	int service;				/* Service type */
+	int connection_id;			/* Connection ID */
+	char *real_id;				/* What ID is logged on */
+	char *active_id;			/* What ID is active */
+
+	/* Flags for the unknown portion of the data */
+	unsigned int magic_id;
+	unsigned int unknown1;
+	unsigned int msgtype;		/* flag for indicating/requesting msg type */
+
+	/* Status flag, I think used at login */
+	int flag;					/* Used at logon for success/alerts? */
+
+	/* Status entries */
+	int idstatus_count;
+	struct yahoo_idstatus **idstatus;	/* Array of status entries for id's */
+
+	/* Conferencing */
+	char *conf_id;				/* id for the conference */
+	char *conf_host;			/* who is hosting the conference */
+	char *conf_user;			/* single username ( used in */
+	/* declined conference/ */
+	/* addinvite / message / */
+	/* logon / logoff ) */
+
+	char **conf_userlist;		/* user list */
+	char *conf_inviter;			/* user who invited you */
+	/* (conference addinvite) */
+
+	char *conf_msg;				/* conference message */
+
+	int conf_type;				/* text(0) or */
+	/* voice(1) conference */
+
+	/* Mail status */
+	int mail_status;
+
+	/* Calendar data */
+	char *cal_url;
+	int cal_type;
+	char *cal_timestamp;
+	char *cal_title;
+	char *cal_description;
+
+	/* Chat invite data */
+	char *chat_invite_content;
+
+	/* Received message */
+	char *msg_id;				/* Originator of message */
+	int msg_status;				/* Status update from the message */
+	char *msg_timestamp;		/* Timestamp of offline message */
+	char *msg;					/* Content of message */
+
+	/* File transfer request */
+	char *file_from;
+	char *file_flag;
+	char *file_url;
+	char *file_description;
+	int file_expires;
+
+	/* Group names for renaming */
+	char *group_old;			/* Old group name */
+	char *group_new;			/* New group name */
+};
+
+/* Misc contants */
+#define YAHOO_PACKET_HEADER_SIZE 104	/* size of a standard header */
+
+/* Status codes */
+struct yahoo_idlabel
+{
+	int id;
+	char *label;
+};
+
+/* Constants for connect mode selection */
+enum
+{
+	YAHOO_CONNECT_NORMAL, YAHOO_CONNECT_HTTP, YAHOO_CONNECT_HTTPPROXY,
+	YAHOO_CONNECT_SOCKS4, YAHOO_CONNECT_SOCKS5
+};
+
+/* Constants for status codes */
+enum
+{
+	YAHOO_STATUS_AVAILABLE,
+	YAHOO_STATUS_BRB,
+	YAHOO_STATUS_BUSY,
+	YAHOO_STATUS_NOTATHOME,
+	YAHOO_STATUS_NOTATDESK,
+	YAHOO_STATUS_NOTINOFFICE,
+	YAHOO_STATUS_ONPHONE,
+	YAHOO_STATUS_ONVACATION,
+	YAHOO_STATUS_OUTTOLUNCH,
+	YAHOO_STATUS_STEPPEDOUT,
+	YAHOO_STATUS_INVISIBLE = 12,
+	YAHOO_STATUS_CUSTOM = 99,
+	YAHOO_STATUS_IDLE = 999
+};
+
+/* Function prototypes */
+#include "libyahoo-proto.h"
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/yay/memtok.c	Fri Nov 03 10:03:53 2000 +0000
@@ -0,0 +1,114 @@
+/* Standard system headers */
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * memtok differs from strtok in a few ways:
+ * The pointer to the buffer to be scanned AND the pointer to the delimiters are NOT NULL terminated
+ * strings but are each a pair of a pointer and byte count (so that NIL characters can be contained
+ * in either of these buffers!
+ *
+ * Also memtok does not replace the "found" delimiter with a NIL character, but places the number
+ * of bytes delimited by that delimiter into the location of the size_t pointer to by found.
+ *
+ * The whole **real** point of this function was that strtok skips any repeating delimiters, but we
+ * need a function that retuns "empty strings" should there be two delimiters in a row.
+ *
+ * For some sense of consistency, the byte count of the buffer to be searched through is ALSO ignored
+ * by memtok iff the buffer to be scanned is NULL
+ *
+ * Here's an example:
+ *
+ * size_t found = 0;
+ * char *tok = 0, *buffer = malloc (COUNT);
+ * fill_buffer_with_some_data (buffer, COUNT);
+ * tok = memtok (buffer, COUNT, "\000\002", 2, &found);
+ *
+ * if tok != NULL then the bytes from tok to (tok + found) are the token
+ * You can then look for more tokens with:
+ *
+ * tok = memtok (NULL, 0, "\000\002", 2, &found);
+ *
+ * If tmp == NULL noone of the delimiters were found, however tmp can != NULL and found CAN == 0
+ *
+ * This means that although a delimiter was found it was immediately preceded by another delimiter and
+ * thus delimited an empty token.
+ *
+ * ( As it happens, if one of the delimiters you want to search for is a NIL character, you can put the
+ * other delimiter characters in a string literal and "lie" about how many delimiter characters there are
+ * because all string literals are NIL terminated!
+ *
+ * Therefor the above example could have been written:
+ * tok = memtok (buffer, COUNT, "\002", 2, &found);
+ *
+ * There are also two supplimentary functions that make using these tokens easier
+ *
+ * memdup is akin to strdup except that instead of it looking for a NIL termination character
+ * it simply mallocs copies the specified number of bytes
+ *
+ * memdupasstr does as memdup except that it mallocs 1 more byte and makes it a NIL char so that you
+ * can treat it as a string (as long as you're sure that the memory being described by the pointer and
+ * byte count don't already contain any NIL characters)
+ *
+ */
+
+/**********************************************************************************************************************************/
+/* Interface (global) functions */
+/**********************************************************************************************************************************/
+char *memtok(char *m, size_t bytes, const char *delims, size_t delim_count,
+	size_t * found)
+{
+	static char *mem = 0, *c = 0;
+	static size_t offset = 0, offset_now = 0, limit = 0;
+
+	if (0 != m)
+	{
+		mem = m;
+		offset = 0;
+		limit = bytes;
+	}
+
+	offset_now = offset;
+
+	for (c = mem; offset < limit; ++offset, ++c)
+	{
+		if (0 != memchr(delims, *c, delim_count))
+		{
+			static char *ret = 0;
+
+			ret = mem;
+			mem = c + 1;
+			*found = offset - offset_now;
+			offset_now = offset + 1;
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+char *memdup(const char *mem, size_t bytes)
+{
+	char *dup = 0;
+
+	if (0 < bytes && 0 != mem)
+	{
+		dup = malloc(bytes);
+		memcpy(dup, mem, bytes);
+	}
+
+	return dup;
+}
+
+char *memdupasstr(const char *mem, size_t bytes)
+{
+	char *string = 0;
+
+	if (0 < bytes && 0 != mem)
+	{
+		string = memdup(mem, bytes + 1);
+		string[bytes] = '\0';
+	}
+
+	return string;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/yay/memtok.h	Fri Nov 03 10:03:53 2000 +0000
@@ -0,0 +1,8 @@
+#ifndef MEMTOK_H
+#define MEMTOK_H
+
+char *memtok (char *m, size_t bytes, const char *delims, size_t delim_count, size_t *found);
+char *memdup (const char *mem, size_t bytes);
+char *memdupasstr (const char *mem, size_t bytes);
+
+#endif /* ndef MEMTOK_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/yay/yay.c	Fri Nov 03 10:03:53 2000 +0000
@@ -0,0 +1,351 @@
+/*
+ * gaim
+ *
+ * Some code copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
+ * libfaim code copyright 1998, 1999 Adam Fritzler <afritz@auk.cx>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "../config.h"
+#endif
+
+
+#include <netdb.h>
+#include <gtk/gtk.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include "multi.h"
+#include "prpl.h"
+#include "gaim.h"
+#include "libyahoo.h"
+
+struct yahoo_data {
+	struct yahoo_context *ctxt;
+};
+
+static char *yahoo_name() {
+	return "Yahoo";
+}
+
+char *name() {
+	return "Yahoo";
+}
+
+char *description() {
+	return "Allows gaim to use the Yahoo protocol";
+}
+
+static void process_packet_status(struct gaim_connection *gc, struct yahoo_packet *pkt) {
+	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+	int i;
+
+	if (pkt->service == YAHOO_SERVICE_LOGOFF && !strcasecmp(pkt->active_id, gc->username)) {
+		signoff(gc);
+		return;
+	}
+
+	for (i = 0; i < pkt->idstatus_count; i++) {
+		struct group *g;
+		struct buddy *b;
+		struct yahoo_idstatus *rec = pkt->idstatus[i];
+
+		b = find_buddy(gc, rec->id);
+		if (!b) {
+			struct yahoo_buddy **buddy;
+			for (buddy = yd->ctxt->buddies; *buddy; buddy++) {
+				struct yahoo_buddy *bud = *buddy;
+
+				if (!strcasecmp(rec->id, bud->id))
+					b = add_buddy(gc, bud->group, bud->id, bud->id);
+			}
+		}
+		if (pkt->service == YAHOO_SERVICE_LOGOFF)
+			serv_got_update(gc, b->name, 0, 0, 0, 0, 0, 0);
+		else
+			serv_got_update(gc, b->name, 1, 0, 0, 0, rec->status, 0);
+	}
+}
+
+static void process_packet_message(struct gaim_connection *gc, struct yahoo_packet *pkt) {
+	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+
+	if (pkt->msg) {
+		if (pkt->msgtype == YAHOO_MSGTYPE_BOUNCE)
+			do_error_dialog("Your message did not get received.", "Error");
+		else
+			serv_got_im(gc, pkt->msg_id, pkt->msg, pkt->msg_timestamp ? 1 : 0);
+	}
+}
+
+static void process_packet_conf_invite(struct gaim_connection *gc, struct yahoo_packet *pkt) {
+	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+}
+
+static void process_packet_conf_add_invite(struct gaim_connection *gc, struct yahoo_packet *pkt) {
+	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+}
+
+static void process_packet_conf_msg(struct gaim_connection *gc, struct yahoo_packet *pkt) {
+	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+}
+
+static void process_packet_conf_logon(struct gaim_connection *gc, struct yahoo_packet *pkt) {
+	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+}
+
+static void process_packet_conf_logoff(struct gaim_connection *gc, struct yahoo_packet *pkt) {
+	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+}
+
+static void process_packet_newmail(struct gaim_connection *gc, struct yahoo_packet *pkt) {
+	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+	char buf[2048];
+
+	if (pkt->mail_status) {
+		if (pkt->service == YAHOO_SERVICE_NEWMAIL)
+			g_snprintf(buf, sizeof buf, "%s has %d new message%s on Yahoo Mail.",
+					gc->username, pkt->mail_status,
+					pkt->mail_status == 1 ? "" : "s");
+		else
+			g_snprintf(buf, sizeof buf, "%s has %d new personal message%s on Yahoo Mail.",
+					gc->username, pkt->mail_status,
+					pkt->mail_status == 1 ? "" : "s");
+		do_error_dialog(buf, "New Mail!");
+	}
+}
+
+static void yahoo_callback(gpointer data, gint source, GdkInputCondition condition) {
+	struct gaim_connection *gc = (struct gaim_connection *)data;
+	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+
+	struct yahoo_rawpacket *rawpkt;
+	struct yahoo_packet *pkt;
+
+	if (!yahoo_getdata(yd->ctxt)) {
+		signoff(gc);
+	}
+
+	while ((rawpkt = yahoo_getpacket(yd->ctxt)) != NULL) {
+		pkt = yahoo_parsepacket(yd->ctxt, rawpkt);
+
+		switch (pkt->service) {
+			case YAHOO_SERVICE_USERSTAT:
+			case YAHOO_SERVICE_CHATLOGON:
+			case YAHOO_SERVICE_CHATLOGOFF:
+			case YAHOO_SERVICE_LOGON:
+			case YAHOO_SERVICE_LOGOFF:
+			case YAHOO_SERVICE_ISAWAY:
+			case YAHOO_SERVICE_ISBACK:
+				process_packet_status(gc, pkt);
+				break;
+			case YAHOO_SERVICE_MESSAGE:
+			case YAHOO_SERVICE_CHATMSG:
+			case YAHOO_SERVICE_SYSMESSAGE:
+				process_packet_message(gc, pkt);
+				break;
+			case YAHOO_SERVICE_CONFINVITE:
+				process_packet_conf_invite(gc, pkt);
+				break;
+			case YAHOO_SERVICE_CONFADDINVITE:
+				process_packet_conf_add_invite(gc, pkt);
+				break;
+			case YAHOO_SERVICE_CONFMSG:
+				process_packet_conf_msg(gc, pkt);
+				break;
+			case YAHOO_SERVICE_CONFLOGON:
+				process_packet_conf_logon(gc, pkt);
+				break;
+			case YAHOO_SERVICE_CONFLOGOFF:
+				process_packet_conf_logoff(gc, pkt);
+				break;
+			case YAHOO_SERVICE_NEWMAIL:
+			case YAHOO_SERVICE_NEWPERSONALMAIL:
+				process_packet_newmail(gc, pkt);
+				break;
+			default:
+				debug_printf("Unhandled packet type %s\n",
+						yahoo_get_service_string(pkt->service));
+				break;
+		}
+		yahoo_free_packet(pkt);
+		yahoo_free_rawpacket(rawpkt);
+	}
+}
+
+static void yahoo_login(struct aim_user *user) {
+	struct gaim_connection *gc = new_gaim_conn(PROTO_YAHOO, user->username, user->password);
+	struct yahoo_data *yd = gc->proto_data = g_new0(struct yahoo_data, 1);
+	int i;
+
+	struct yahoo_options opt;
+	struct yahoo_context *ctxt;
+	opt.connect_mode = YAHOO_CONNECT_NORMAL;
+	opt.proxy_host = NULL;
+	ctxt = yahoo_init(user->username, user->password, &opt);
+	yd->ctxt = ctxt;
+
+	set_login_progress(gc, 1, "Connecting");
+	while (gtk_events_pending())
+		gtk_main_iteration();
+
+	if (!ctxt || !yahoo_connect(ctxt)) {
+		debug_printf("Yahoo: Unable to connect\n");
+		hide_login_progress(gc, "Unable to connect");
+		destroy_gaim_conn(gc);
+		return;
+	}
+
+	debug_printf("Yahoo: connected\n");
+
+	set_login_progress(gc, 3, "Getting Config");
+	while (gtk_events_pending())
+		gtk_main_iteration();
+
+	yahoo_get_config(ctxt);
+
+	if (yahoo_cmd_logon(ctxt, YAHOO_STATUS_AVAILABLE)) {
+		debug_printf("Yahoo: Unable to login\n");
+		hide_login_progress(gc, "Unable to login");
+		destroy_gaim_conn(gc);
+		return;
+	}
+
+	if (ctxt->buddies) {
+		struct yahoo_buddy **buddies;
+		
+		for (buddies = ctxt->buddies; *buddies; buddies++) {
+			struct yahoo_buddy *bud = *buddies;
+			struct buddy *b;
+			struct group *g;
+
+			b = find_buddy(gc, bud->id);
+			if (!b) add_buddy(gc, bud->group, bud->id, bud->id);
+		}
+	}
+
+	debug_printf("Yahoo: logged in %s\n", gc->username);
+	account_online(user, gc);
+	serv_finish_login(gc);
+
+	gc->inpa = gdk_input_add(ctxt->sockfd, GDK_INPUT_READ | GDK_INPUT_EXCEPTION,
+				yahoo_callback, gc);
+}
+
+static void yahoo_close(struct gaim_connection *gc) {
+	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+	if (gc->inpa)
+		gdk_input_remove(gc->inpa);
+	gc->inpa = -1;
+	yahoo_cmd_logoff(yd->ctxt);
+	g_free(yd);
+}
+
+static void yahoo_send_im(struct gaim_connection *gc, char *who, char *message, int away) {
+	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+
+	yahoo_cmd_msg(yd->ctxt, gc->username, who, message);
+}
+
+static void yahoo_set_idle(struct gaim_connection *gc, int idle) {
+	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+
+	if (idle)
+		yahoo_cmd_set_away_mode(yd->ctxt, YAHOO_STATUS_IDLE, NULL);
+	else
+		yahoo_cmd_set_back_mode(yd->ctxt, YAHOO_STATUS_AVAILABLE, NULL);
+}
+
+static void yahoo_keepalive(struct gaim_connection *gc) {
+	yahoo_cmd_ping(((struct yahoo_data *)gc->proto_data)->ctxt);
+}
+
+static void gyahoo_add_buddy(struct gaim_connection *gc, char *name) {
+	struct yahoo_data *yd = (struct yahoo_data *)gc->proto_data;
+	struct yahoo_buddy *tmpbuddy;
+	struct group *g = find_group_by_buddy(gc, name);
+	char *group = NULL;
+
+	if (g) {
+		group = g->name;
+	} else if (yd->ctxt && yd->ctxt->buddies[0]) {
+		tmpbuddy = yd->ctxt->buddies[0];
+		group = tmpbuddy->group;
+	}
+
+	if (group)
+		yahoo_add_buddy(yd->ctxt, name, gc->username, group, "");
+}
+
+static struct prpl *my_protocol = NULL;
+
+void Yahoo_init(struct prpl *ret) {
+	/* the NULL's aren't required but they're nice to have */
+	ret->protocol = PROTO_YAHOO;
+	ret->name = yahoo_name;
+	ret->list_icon = NULL;
+	ret->action_menu = NULL;
+	ret->login = yahoo_login;
+	ret->close = yahoo_close;
+	ret->send_im = yahoo_send_im;
+	ret->set_info = NULL;
+	ret->get_info = NULL;
+	ret->set_away = NULL;
+	ret->get_away_msg = NULL;
+	ret->set_dir = NULL;
+	ret->get_dir = NULL;
+	ret->dir_search = NULL;
+	ret->set_idle = yahoo_set_idle;
+	ret->change_passwd = NULL;
+	ret->add_buddy = gyahoo_add_buddy;
+	ret->add_buddies = NULL;
+	ret->remove_buddy = NULL;
+	ret->add_permit = NULL;
+	ret->add_deny = NULL;
+	ret->rem_permit = NULL;
+	ret->rem_deny = NULL;
+	ret->set_permit_deny = NULL;
+	ret->warn = NULL;
+	ret->accept_chat = NULL;
+	ret->join_chat = NULL;
+	ret->chat_invite = NULL;
+	ret->chat_leave = NULL;
+	ret->chat_whisper = NULL;
+	ret->chat_send = NULL;
+	ret->keepalive = yahoo_keepalive;
+
+	my_protocol = ret;
+}
+
+char *gaim_plugin_init(GModule *handle) {
+	load_protocol(Yahoo_init);
+	return NULL;
+}
+
+void gaim_plugin_remove() {
+	struct prpl *p = find_prpl(PROTO_YAHOO);
+	if (p == my_protocol)
+		unload_protocol(p);
+}