Index: protocols/account.c
===================================================================
--- protocols/account.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ protocols/account.c	(revision e5d2c5607310ef9669a051a1b93e019319495955)
@@ -86,11 +86,5 @@
 	/* Hardcode some more clever tag guesses. */
 	strcpy(tag, prpl->name);
-	if (strcmp(prpl->name, "oscar") == 0) {
-		if (g_ascii_isdigit(a->user[0])) {
-			strcpy(tag, "icq");
-		} else {
-			strcpy(tag, "aim");
-		}
-	} else if (strcmp(prpl->name, "jabber") == 0) {
+	if (strcmp(prpl->name, "jabber") == 0) {
 		if (strstr(a->user, "@gmail.com") ||
 		    strstr(a->user, "@googlemail.com")) {
Index: protocols/nogaim.c
===================================================================
--- protocols/nogaim.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ protocols/nogaim.c	(revision e5d2c5607310ef9669a051a1b93e019319495955)
@@ -240,9 +240,4 @@
 
 #else
-	if (strcmp(name, "aim") == 0 || strcmp(name, "icq") == 0) {
-		return g_strdup("This account uses libpurple specific aliases for oscar. "
-		                "Re-add the account with `account add oscar ...'");
-	}
-
 	extramsg = "If this is a libpurple plugin, you might need to install bitlbee-libpurple instead.";
 #endif
@@ -254,12 +249,7 @@
 void nogaim_init()
 {
-	extern void oscar_initmodule();
 	extern void jabber_initmodule();
 	extern void twitter_initmodule();
 	extern void purple_initmodule();
-
-#ifdef WITH_OSCAR
-	oscar_initmodule();
-#endif
 
 #ifdef WITH_JABBER
Index: protocols/oscar/AUTHORS
===================================================================
--- protocols/oscar/AUTHORS	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,31 +1,0 @@
-
-Anyone else want to be in here?
-
----
-
-N: Adam Fritzler
-H: mid
-E: mid@auk.cx
-W: http://www.auk.cx/~mid,http://www.auk.cx/faim
-D: Wrote most of the wap of crap that you see before you.
-
-N: Josh Myer
-E: josh@joshisanerd.com
-D: OFT/ODC (not quite finished yet..), random little things, Munger-At-Large, compile-time warnings.
-
-N: Daniel Reed
-H: n, linuxkitty
-E: n@ml.org
-W: http://users.n.ml.org/n/
-D: Fixed aim_snac.c
-
-N: Eric Warmenhoven
-E: warmenhoven@linux.com
-D: Some OFT info, author of the faim interface for gaim
-
-N: Brock Wilcox
-H: awwaiid
-E: awwaiid@auk.cx
-D: Figured out original password roasting
-
-
Index: protocols/oscar/COPYING
===================================================================
--- protocols/oscar/COPYING	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,513 +1,0 @@
-		  GNU LESSER GENERAL PUBLIC LICENSE
-		       Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
-     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL.  It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
-  This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it.  You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
-  When we speak of free software, we are referring to freedom of use,
-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 and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
-  To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights.  These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
-  For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you.  You must make sure that they, too, receive or can get the source
-code.  If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it.  And you must show them these terms so they know their rights.
-
-  We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
-  To protect each distributor, we want to make it very clear that
-there is no warranty for the free library.  Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
-
-  Finally, software patents pose a constant threat to the existence of
-any free program.  We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder.  Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
-  Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License.  This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License.  We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
-  When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library.  The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom.  The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
-  We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License.  It also provides other free software developers Less
-of an advantage over competing non-free programs.  These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries.  However, the Lesser license provides advantages in certain
-special circumstances.
-
-  For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard.  To achieve this, non-free programs must be
-allowed to use the library.  A more frequent case is that a free
-library does the same job as widely used non-free libraries.  In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
-  In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software.  For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
-  Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.  Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library".  The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
-
-		  GNU LESSER GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
-  A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
-  The "Library", below, refers to any such software library or work
-which has been distributed under these terms.  A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language.  (Hereinafter, translation is
-included without limitation in the term "modification".)
-
-  "Source code" for a work means the preferred form of the work for
-making modifications to it.  For a library, 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 library.
-
-  Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it).  Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-  
-  1. You may copy and distribute verbatim copies of the Library's
-complete 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 distribute a copy of this License along with the
-Library.
-
-  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 Library or any portion
-of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
-
-    b) You must cause the files modified to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    c) You must cause the whole of the work to be licensed at no
-    charge to all third parties under the terms of this License.
-
-    d) If a facility in the modified Library refers to a function or a
-    table of data to be supplied by an application program that uses
-    the facility, other than as an argument passed when the facility
-    is invoked, then you must make a good faith effort to ensure that,
-    in the event an application does not supply such function or
-    table, the facility still operates, and performs whatever part of
-    its purpose remains meaningful.
-
-    (For example, a function in a library to compute square roots has
-    a purpose that is entirely well-defined independent of the
-    application.  Therefore, Subsection 2d requires that any
-    application-supplied function or table used by this function must
-    be optional: if the application does not supply it, the square
-    root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Library,
-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 Library, 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 Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library.  To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License.  (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.)  Do not make any other change in
-these notices.
-
-
-  Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
-  This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
-  4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you 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.
-
-  If distribution of 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 satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library".  Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
-  However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library".  The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
-  When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library.  The
-threshold for this to be true is not precisely defined by law.
-
-  If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work.  (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
-  Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
-
-  6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
-  You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License.  You must supply a copy of this License.  If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License.  Also, you must do one
-of these things:
-
-    a) Accompany the work with the complete corresponding
-    machine-readable source code for the Library including whatever
-    changes were used in the work (which must be distributed under
-    Sections 1 and 2 above); and, if the work is an executable linked
-    with the Library, with the complete machine-readable "work that
-    uses the Library", as object code and/or source code, so that the
-    user can modify the Library and then relink to produce a modified
-    executable containing the modified Library.  (It is understood
-    that the user who changes the contents of definitions files in the
-    Library will not necessarily be able to recompile the application
-    to use the modified definitions.)
-
-    b) Use a suitable shared library mechanism for linking with the
-    Library.  A suitable mechanism is one that (1) uses at run time a
-    copy of the library already present on the user's computer system,
-    rather than copying library functions into the executable, and (2)
-    will operate properly with a modified version of the library, if
-    the user installs one, as long as the modified version is
-    interface-compatible with the version that the work was made with.
-
-    c) Accompany the work with a written offer, valid for at
-    least three years, to give the same user the materials
-    specified in Subsection 6a, above, for a charge no more
-    than the cost of performing this distribution.
-
-    d) If distribution of the work is made by offering access to copy
-    from a designated place, offer equivalent access to copy the above
-    specified materials from the same place.
-
-    e) Verify that the user has already received a copy of these
-    materials or that you have already sent this user a copy.
-
-  For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it.  However, as a special exception,
-the materials to be 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.
-
-  It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system.  Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
-
-  7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
-    a) Accompany the combined library with a copy of the same work
-    based on the Library, uncombined with any other library
-    facilities.  This must be distributed under the terms of the
-    Sections above.
-
-    b) Give prominent notice with the combined library of the fact
-    that part of it is a work based on the Library, and explaining
-    where to find the accompanying uncombined form of the same work.
-
-  8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License.  Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library 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.
-
-  9. 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 Library or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
-  10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-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 with
-this License.
-
-
-  11. 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 Library at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Library 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 Library.
-
-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.
-
-  12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library 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.
-
-  13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser 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 Library
-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 Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
-
-  14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-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
-
-  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "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
-LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. 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 LIBRARY 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
-LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-
-           How to Apply These Terms to Your New Libraries
-
-  If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change.  You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
-  To apply these terms, attach the following notices to the library.  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 library's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Lesser General Public
-    License as published by the Free Software Foundation; either
-    version 2 of the License, or (at your option) any later version.
-
-    This library 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
-    Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public
-    License along with this library; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the
-  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
-  <signature of Ty Coon>, 1 April 1990
-  Ty Coon, President of Vice
-
-That's all there is to it!
-
-
Index: protocols/oscar/Makefile
===================================================================
--- protocols/oscar/Makefile	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,47 +1,0 @@
-###########################
-## Makefile for BitlBee  ##
-##                       ##
-## Copyright 2002 Lintux ##
-###########################
-
-### DEFINITIONS
-
--include ../../Makefile.settings
-ifdef _SRCDIR_
-_SRCDIR_ := $(_SRCDIR_)protocols/oscar/
-CFLAGS += -I$(_SRCDIR_)
-endif
-
-# [SH] Program variables
-objects = admin.o auth.o bos.o buddylist.o chat.o chatnav.o conn.o icq.o im.o info.o misc.o msgcookie.o rxhandlers.o rxqueue.o search.o service.o snac.o ssi.o stats.o tlv.o txqueue.o oscar_util.o oscar.o
-
-LFLAGS += -r
-
-# [SH] Phony targets
-all: oscar_mod.o
-check: all
-lcov: check
-gcov:
-	gcov *.c
-
-.PHONY: all clean distclean
-
-clean:
-	rm -f *.o core
-
-distclean: clean
-	rm -rf .depend
-
-### MAIN PROGRAM
-
-$(objects): ../../Makefile.settings Makefile
-
-$(objects): %.o: $(_SRCDIR_)%.c
-	@echo '*' Compiling $<
-	$(VERBOSE) $(CC) -c $(CFLAGS) $(CFLAGS_BITLBEE) $< -o $@
-
-oscar_mod.o: $(objects)
-	@echo '*' Linking oscar_mod.o
-	$(VERBOSE) $(LD) $(LFLAGS) $(objects) -o oscar_mod.o
-
--include .depend/*.d
Index: protocols/oscar/admin.c
===================================================================
--- protocols/oscar/admin.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,206 +1,0 @@
-#include <aim.h>
-#include "admin.h"
-
-/* called for both reply and change-reply */
-static int infochange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	/*
-	 * struct {
-	 *    guint16 perms;
-	 *    guint16 tlvcount;
-	 *    aim_tlv_t tlvs[tlvcount];
-	 *  } admin_info[n];
-	 */
-	while (aim_bstream_empty(bs)) {
-		guint16 perms, tlvcount;
-
-		perms = aimbs_get16(bs);
-		tlvcount = aimbs_get16(bs);
-
-		while (tlvcount && aim_bstream_empty(bs)) {
-			aim_rxcallback_t userfunc;
-			guint16 type, len;
-			guint8 *val;
-			int str = 0;
-
-			type = aimbs_get16(bs);
-			len = aimbs_get16(bs);
-
-			if ((type == 0x0011) || (type == 0x0004)) {
-				str = 1;
-			}
-
-			if (str) {
-				val = (guint8 *) aimbs_getstr(bs, len);
-			} else {
-				val = aimbs_getraw(bs, len);
-			}
-
-			/* XXX fix so its only called once for the entire packet */
-			if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-				userfunc(sess, rx, (snac->subtype == 0x0005) ? 1 : 0, perms, type, len, val, str);
-			}
-
-			g_free(val);
-
-			tlvcount--;
-		}
-	}
-
-	return 1;
-}
-
-static int accountconfirm(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac,
-                          aim_bstream_t *bs)
-{
-	aim_rxcallback_t userfunc;
-	guint16 status;
-
-	status = aimbs_get16(bs);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		return userfunc(sess, rx, status);
-	}
-
-	return 0;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if ((snac->subtype == 0x0003) || (snac->subtype == 0x0005)) {
-		return infochange(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == 0x0007) {
-		return accountconfirm(sess, mod, rx, snac, bs);
-	}
-
-	return 0;
-}
-
-int admin_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = AIM_CB_FAM_ADM;
-	mod->version = 0x0001;
-	mod->toolid = AIM_TOOL_NEWWIN;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "admin", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
-
-int aim_admin_changepasswd(aim_session_t *sess, aim_conn_t *conn, const char *newpw, const char *curpw)
-{
-	aim_frame_t *tx;
-	aim_tlvlist_t *tl = NULL;
-	aim_snacid_t snacid;
-
-	if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + strlen(curpw) + 4 + strlen(newpw)))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, 0x0007, 0x0004, 0x0000, NULL, 0);
-	aim_putsnac(&tx->data, 0x0007, 0x0004, 0x0000, snacid);
-
-	/* new password TLV t(0002) */
-	aim_addtlvtochain_raw(&tl, 0x0002, strlen(newpw), (guint8 *) newpw);
-
-	/* current password TLV t(0012) */
-	aim_addtlvtochain_raw(&tl, 0x0012, strlen(curpw), (guint8 *) curpw);
-
-	aim_writetlvchain(&tx->data, &tl);
-	aim_freetlvchain(&tl);
-
-	aim_tx_enqueue(sess, tx);
-
-	return 0;
-}
-
-/*
- * Request account confirmation.
- *
- * This will cause an email to be sent to the address associated with
- * the account.  By following the instructions in the mail, you can
- * get the TRIAL flag removed from your account.
- *
- */
-int aim_admin_reqconfirm(aim_session_t *sess, aim_conn_t *conn)
-{
-	return aim_genericreq_n(sess, conn, 0x0007, 0x0006);
-}
-
-/*
- * Request a bit of account info.
- *
- * The only known valid tag is 0x0011 (email address).
- *
- */
-int aim_admin_getinfo(aim_session_t *sess, aim_conn_t *conn, guint16 info)
-{
-	aim_frame_t *tx;
-	aim_snacid_t snacid;
-
-	if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 14))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, 0x0002, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&tx->data, 0x0007, 0x0002, 0x0000, snacid);
-
-	aimbs_put16(&tx->data, info);
-	aimbs_put16(&tx->data, 0x0000);
-
-	aim_tx_enqueue(sess, tx);
-
-	return 0;
-}
-
-int aim_admin_setemail(aim_session_t *sess, aim_conn_t *conn, const char *newemail)
-{
-	aim_frame_t *tx;
-	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
-
-	if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 2 + 2 + strlen(newemail)))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, 0x0007, 0x0004, 0x0000, NULL, 0);
-	aim_putsnac(&tx->data, 0x0007, 0x0004, 0x0000, snacid);
-
-	aim_addtlvtochain_raw(&tl, 0x0011, strlen(newemail), (guint8 *) newemail);
-
-	aim_writetlvchain(&tx->data, &tl);
-	aim_freetlvchain(&tl);
-
-	aim_tx_enqueue(sess, tx);
-
-	return 0;
-}
-
-int aim_admin_setnick(aim_session_t *sess, aim_conn_t *conn, const char *newnick)
-{
-	aim_frame_t *tx;
-	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
-
-	if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 2 + 2 + strlen(newnick)))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, 0x0007, 0x0004, 0x0000, NULL, 0);
-	aim_putsnac(&tx->data, 0x0007, 0x0004, 0x0000, snacid);
-
-	aim_addtlvtochain_raw(&tl, 0x0001, strlen(newnick), (guint8 *) newnick);
-
-	aim_writetlvchain(&tx->data, &tl);
-	aim_freetlvchain(&tl);
-
-	aim_tx_enqueue(sess, tx);
-
-
-	return 0;
-}
Index: protocols/oscar/admin.h
===================================================================
--- protocols/oscar/admin.h	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,13 +1,0 @@
-#ifndef __OSCAR_ADMIN_H__
-#define __OSCAR_ADMIN_H__
-
-#define AIM_CB_FAM_ADM 0x0007
-
-/*
- * SNAC Family: Administrative Services.
- */
-#define AIM_CB_ADM_ERROR 0x0001
-#define AIM_CB_ADM_INFOCHANGE_REPLY 0x0005
-#define AIM_CB_ADM_DEFAULT 0xffff
-
-#endif /* __OSCAR_ADMIN_H__ */
Index: protocols/oscar/aim.h
===================================================================
--- protocols/oscar/aim.h	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,892 +1,0 @@
-/*
- * Main libfaim header.  Must be included in client for prototypes/macros.
- *
- * "come on, i turned a chick lesbian; i think this is the hackish equivalent"
- *                                                -- Josh Meyer
- *
- */
-
-#ifndef __AIM_H__
-#define __AIM_H__
-
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <time.h>
-#include <gmodule.h>
-
-#include "bitlbee.h"
-
-#ifdef WITH_PURPLE
-/* For compatibility with builds that include both purple and this oscar module */
-#include "aim_prefixes.h"
-#endif
-
-/* XXX adjust these based on autoconf-detected platform */
-typedef guint32 aim_snacid_t;
-typedef guint16 flap_seqnum_t;
-
-/* Portability stuff (DMP) */
-
-#if defined(mach) && defined(__APPLE__)
-#define gethostbyname(x) gethostbyname2(x, AF_INET)
-#endif
-
-/*
- * Current Maximum Length for Screen Names (not including NULL)
- *
- * Currently only names up to 16 characters can be registered
- * however it is aparently legal for them to be larger.
- */
-#define MAXSNLEN 32
-
-/*
- * Current Maximum Length for Instant Messages
- *
- * This was found basically by experiment, but not wholly
- * accurate experiment.  It should not be regarded
- * as completely correct.  But its a decent approximation.
- *
- * Note that although we can send this much, its impossible
- * for WinAIM clients (up through the latest (4.0.1957)) to
- * send any more than 1kb.  Amaze all your windows friends
- * with utterly oversized instant messages!
- *
- * XXX: the real limit is the total SNAC size at 8192. Fix this.
- *
- */
-#define MAXMSGLEN 7987
-
-/*
- * Maximum size of a Buddy Icon.
- */
-#define MAXICONLEN 7168
-#define AIM_ICONIDENT "AVT1picture.id"
-
-/*
- * Current Maximum Length for Chat Room Messages
- *
- * This is actually defined by the protocol to be
- * dynamic, but I have yet to see due cause to
- * define it dynamically here.  Maybe later.
- *
- */
-#define MAXCHATMSGLEN 512
-
-/*
- * Standard size of an AIM authorization cookie
- */
-#define AIM_COOKIELEN            0x100
-
-#define AIM_MD5_STRING "AOL Instant Messenger (SM)"
-
-/*
- * Default Authorizer server name and TCP port for the OSCAR farm.
- *
- * You shouldn't need to change this unless you're writing
- * your own server.
- *
- * Note that only one server is needed to start the whole
- * AIM process.  The later server addresses come from
- * the authorizer service.
- *
- * This is only here for convenience.  Its still up to
- * the client to connect to it.
- *
- */
-#define AIM_DEFAULT_LOGIN_SERVER_AIM "login.messaging.aol.com"
-#define AIM_DEFAULT_LOGIN_SERVER_ICQ "login.icq.com"
-#define AIM_LOGIN_PORT 5190
-
-/*
- * Size of the SNAC caching hash.
- *
- * Default: 16
- *
- */
-#define AIM_SNAC_HASH_SIZE 16
-
-/*
- * Client info.  Filled in by the client and passed in to
- * aim_send_login().  The information ends up getting passed to OSCAR
- * through the initial login command.
- *
- */
-struct client_info_s {
-	const char *clientstring;
-	guint16 clientid;
-	int major;
-	int minor;
-	int point;
-	int build;
-	const char *country; /* two-letter abbrev */
-	const char *lang; /* two-letter abbrev */
-};
-
-#define AIM_CLIENTINFO_KNOWNGOOD_3_5_1670 { \
-		"AOL Instant Messenger (SM), version 3.5.1670/WIN32", \
-		0x0004, \
-		0x0003, \
-		0x0005, \
-		0x0000, \
-		0x0686, \
-		"us", \
-		"en", \
-}
-
-#define AIM_CLIENTINFO_KNOWNGOOD_4_1_2010 { \
-		"AOL Instant Messenger (SM), version 4.1.2010/WIN32", \
-		0x0004, \
-		0x0004, \
-		0x0001, \
-		0x0000, \
-		0x07da, \
-		"us", \
-		"en", \
-}
-
-#define AIM_CLIENTINFO_KNOWNGOOD_5_1_3036 { \
-		"AOL Instant Messenger, version 5.1.3036/WIN32", \
-		0x0109, \
-		0x0005, \
-		0x0001, \
-		0x0000, \
-		0x0bdc, \
-		"us", \
-		"en", \
-}
-
-/*
- * I would make 4.1.2010 the default, but they seem to have found
- * an alternate way of breaking that one.
- *
- * 3.5.1670 should work fine, however, you will be subjected to the
- * memory test, which may require you to have a WinAIM binary laying
- * around. (see login.c::memrequest())
- */
-#define AIM_CLIENTINFO_KNOWNGOOD AIM_CLIENTINFO_KNOWNGOOD_5_1_3036
-
-#ifndef TRUE
-#define TRUE 1
-#define FALSE 0
-#endif
-
-/*
- * These could be arbitrary, but its easier to use the actual AIM values
- */
-#define AIM_CONN_TYPE_AUTH          0x0007
-#define AIM_CONN_TYPE_ADS           0x0005
-#define AIM_CONN_TYPE_BOS           0x0002
-#define AIM_CONN_TYPE_CHAT          0x000e
-#define AIM_CONN_TYPE_CHATNAV       0x000d
-
-/*
- * Status values returned from aim_conn_new().  ORed together.
- */
-#define AIM_CONN_STATUS_READY       0x0001
-#define AIM_CONN_STATUS_INTERNALERR 0x0002
-#define AIM_CONN_STATUS_RESOLVERR   0x0040
-#define AIM_CONN_STATUS_CONNERR     0x0080
-#define AIM_CONN_STATUS_INPROGRESS  0x0100
-
-#define AIM_FRAMETYPE_FLAP 0x0000
-
-/*
- * message type flags
- */
-#define AIM_MTYPE_PLAIN     0x01
-#define AIM_MTYPE_CHAT      0x02
-#define AIM_MTYPE_FILEREQ   0x03
-#define AIM_MTYPE_URL       0x04
-#define AIM_MTYPE_AUTHREQ   0x06
-#define AIM_MTYPE_AUTHDENY  0x07
-#define AIM_MTYPE_AUTHOK    0x08
-#define AIM_MTYPE_SERVER    0x09
-#define AIM_MTYPE_ADDED     0x0C
-#define AIM_MTYPE_WWP       0x0D
-#define AIM_MTYPE_EEXPRESS  0x0E
-#define AIM_MTYPE_CONTACTS  0x13
-#define AIM_MTYPE_PLUGIN    0x1A
-#define AIM_MTYPE_AUTOAWAY      0xE8
-#define AIM_MTYPE_AUTOBUSY      0xE9
-#define AIM_MTYPE_AUTONA        0xEA
-#define AIM_MTYPE_AUTODND       0xEB
-#define AIM_MTYPE_AUTOFFC       0xEC
-
-typedef struct aim_conn_s {
-	int fd;
-	guint16 type;
-	guint16 subtype;
-	flap_seqnum_t seqnum;
-	guint32 status;
-	void *priv; /* misc data the client may want to store */
-	void *internal; /* internal conn-specific libfaim data */
-	time_t lastactivity; /* time of last transmit */
-	int forcedlatency;
-	void *handlerlist;
-	void *sessv; /* pointer to parent session */
-	void *inside; /* only accessible from inside libfaim */
-	struct aim_conn_s *next;
-} aim_conn_t;
-
-/*
- * Byte Stream type. Sort of.
- *
- * Use of this type serves a couple purposes:
- *   - Buffer/buflen pairs are passed all around everywhere. This turns
- *     that into one value, as well as abstracting it slightly.
- *   - Through the abstraction, it is possible to enable bounds checking
- *     for robustness at the cost of performance.  But a clean failure on
- *     weird packets is much better than a segfault.
- *   - I like having variables named "bs".
- *
- * Don't touch the insides of this struct.  Or I'll have to kill you.
- *
- */
-typedef struct aim_bstream_s {
-	guint8 *data;
-	guint32 len;
-	guint32 offset;
-} aim_bstream_t;
-
-typedef struct aim_frame_s {
-	guint8 hdrtype; /* defines which piece of the union to use */
-	union {
-		struct {
-			guint8 type;
-			flap_seqnum_t seqnum;
-		} flap;
-	} hdr;
-	aim_bstream_t data;     /* payload stream */
-	guint8 handled;         /* 0 = new, !0 = been handled */
-	guint8 nofree;          /* 0 = free data on purge, 1 = only unlink */
-	aim_conn_t *conn;  /* the connection it came in on... */
-	struct aim_frame_s *next;
-} aim_frame_t;
-
-typedef struct aim_msgcookie_s {
-	unsigned char cookie[8];
-	int type;
-	void *data;
-	time_t addtime;
-	struct aim_msgcookie_s *next;
-} aim_msgcookie_t;
-
-/*
- * AIM Session: The main client-data interface.
- *
- */
-typedef struct aim_session_s {
-
-	/* ---- Client Accessible ------------------------ */
-
-	/* Our screen name. */
-	char sn[MAXSNLEN + 1];
-
-	/*
-	 * Pointer to anything the client wants to
-	 * explicitly associate with this session.
-	 *
-	 * This is for use in the callbacks mainly. In any
-	 * callback, you can access this with sess->aux_data.
-	 *
-	 */
-	void *aux_data;
-
-	/* ---- Internal Use Only ------------------------ */
-
-	/* Server-stored information (ssi) */
-	struct {
-		int received_data;
-		guint16 revision;
-		struct aim_ssi_item *items;
-		time_t timestamp;
-		int waiting_for_ack;
-		aim_frame_t *holding_queue;
-	} ssi;
-
-	/* Connection information */
-	aim_conn_t *connlist;
-
-	/*
-	 * Transmit/receive queues.
-	 *
-	 * These are only used when you don't use your own lowlevel
-	 * I/O.  I don't suggest that you use libfaim's internal I/O.
-	 * Its really bad and the API/event model is quirky at best.
-	 *
-	 */
-	aim_frame_t *queue_outgoing;
-	aim_frame_t *queue_incoming;
-
-	/*
-	 * Tx Enqueuing function.
-	 *
-	 * This is how you override the transmit direction of libfaim's
-	 * internal I/O.  This function will be called whenever it needs
-	 * to send something.
-	 *
-	 */
-	int (*tx_enqueue)(struct aim_session_s *, aim_frame_t *);
-
-	/*
-	 * Outstanding snac handling
-	 *
-	 * XXX: Should these be per-connection? -mid
-	 */
-	void *snac_hash[AIM_SNAC_HASH_SIZE];
-	aim_snacid_t snacid_next;
-
-	struct aim_icq_info *icq_info;
-	struct aim_oft_info *oft_info;
-	struct aim_authresp_info *authinfo;
-	struct aim_emailinfo *emailinfo;
-
-	struct {
-		struct aim_userinfo_s *userinfo;
-		struct userinfo_node *torequest;
-		struct userinfo_node *requested;
-		int waiting_for_response;
-	} locate;
-
-	guint32 flags; /* AIM_SESS_FLAGS_ */
-
-	aim_msgcookie_t *msgcookies;
-
-	void *modlistv;
-
-	guint8 aim_icq_state;  /* ICQ representation of away state */
-} aim_session_t;
-
-/* Values for sess->flags */
-#define AIM_SESS_FLAGS_SNACLOGIN         0x00000001
-#define AIM_SESS_FLAGS_NONBLOCKCONNECT   0x00000004
-#define AIM_SESS_FLAGS_DONTTIMEOUTONICBM 0x00000008
-
-/* Valid for calling aim_icq_setstatus() and for aim_userinfo_t->icqinfo.status */
-#define AIM_ICQ_STATE_NORMAL    0x00000000
-#define AIM_ICQ_STATE_AWAY      0x00000001
-#define AIM_ICQ_STATE_DND       0x00000002
-#define AIM_ICQ_STATE_OUT       0x00000004
-#define AIM_ICQ_STATE_BUSY      0x00000010
-#define AIM_ICQ_STATE_CHAT      0x00000020
-#define AIM_ICQ_STATE_INVISIBLE 0x00000100
-#define AIM_ICQ_STATE_WEBAWARE  0x00010000
-#define AIM_ICQ_STATE_HIDEIP            0x00020000
-#define AIM_ICQ_STATE_BIRTHDAY          0x00080000
-#define AIM_ICQ_STATE_DIRECTDISABLED    0x00100000
-#define AIM_ICQ_STATE_ICQHOMEPAGE       0x00200000
-#define AIM_ICQ_STATE_DIRECTREQUIREAUTH 0x10000000
-#define AIM_ICQ_STATE_DIRECTCONTACTLIST 0x20000000
-
-/*
- * AIM User Info, Standard Form.
- */
-typedef struct {
-	char sn[MAXSNLEN + 1];
-	guint16 warnlevel;
-	guint16 idletime;
-	guint16 flags;
-	guint32 membersince;
-	guint32 onlinesince;
-	guint32 sessionlen;
-	guint32 capabilities;
-	struct {
-		guint32 status;
-		guint32 ipaddr;
-		guint8 crap[0x25]; /* until we figure it out... */
-	} icqinfo;
-	guint32 present;
-} aim_userinfo_t;
-
-#define AIM_USERINFO_PRESENT_FLAGS        0x00000001
-#define AIM_USERINFO_PRESENT_MEMBERSINCE  0x00000002
-#define AIM_USERINFO_PRESENT_ONLINESINCE  0x00000004
-#define AIM_USERINFO_PRESENT_IDLE         0x00000008
-#define AIM_USERINFO_PRESENT_ICQEXTSTATUS 0x00000010
-#define AIM_USERINFO_PRESENT_ICQIPADDR    0x00000020
-#define AIM_USERINFO_PRESENT_ICQDATA      0x00000040
-#define AIM_USERINFO_PRESENT_CAPABILITIES 0x00000080
-#define AIM_USERINFO_PRESENT_SESSIONLEN   0x00000100
-
-#define AIM_FLAG_UNCONFIRMED    0x0001 /* "damned transients" */
-#define AIM_FLAG_ADMINISTRATOR  0x0002
-#define AIM_FLAG_AOL            0x0004
-#define AIM_FLAG_OSCAR_PAY      0x0008
-#define AIM_FLAG_FREE           0x0010
-#define AIM_FLAG_AWAY           0x0020
-#define AIM_FLAG_ICQ            0x0040
-#define AIM_FLAG_WIRELESS       0x0080
-#define AIM_FLAG_UNKNOWN100     0x0100
-#define AIM_FLAG_UNKNOWN200     0x0200
-#define AIM_FLAG_ACTIVEBUDDY    0x0400
-#define AIM_FLAG_UNKNOWN800     0x0800
-#define AIM_FLAG_ABINTERNAL     0x1000
-
-#define AIM_FLAG_ALLUSERS       0x001f
-
-/*
- * TLV handling
- */
-
-/* Generic TLV structure. */
-typedef struct aim_tlv_s {
-	guint16 type;
-	guint16 length;
-	guint8 *value;
-} aim_tlv_t;
-
-/* List of above. */
-typedef struct aim_tlvlist_s {
-	aim_tlv_t *tlv;
-	struct aim_tlvlist_s *next;
-} aim_tlvlist_t;
-
-/* TLV-handling functions */
-
-#if 0
-/* Very, very raw TLV handling. */
-int aim_puttlv_8(guint8 *buf, const guint16 t, const guint8 v);
-int aim_puttlv_16(guint8 *buf, const guint16 t, const guint16 v);
-int aim_puttlv_32(guint8 *buf, const guint16 t, const guint32 v);
-int aim_puttlv_raw(guint8 *buf, const guint16 t, const guint16 l, const guint8 *v);
-#endif
-
-/* TLV list handling. */
-aim_tlvlist_t *aim_readtlvchain(aim_bstream_t *bs);
-void aim_freetlvchain(aim_tlvlist_t **list);
-aim_tlv_t *aim_gettlv(aim_tlvlist_t *list, guint16 t, const int n);
-char *aim_gettlv_str(aim_tlvlist_t *list, const guint16 t, const int n);
-guint8 aim_gettlv8(aim_tlvlist_t *list, const guint16 type, const int num);
-guint16 aim_gettlv16(aim_tlvlist_t *list, const guint16 t, const int n);
-guint32 aim_gettlv32(aim_tlvlist_t *list, const guint16 t, const int n);
-int aim_writetlvchain(aim_bstream_t *bs, aim_tlvlist_t **list);
-int aim_addtlvtochain8(aim_tlvlist_t **list, const guint16 t, const guint8 v);
-int aim_addtlvtochain16(aim_tlvlist_t **list, const guint16 t, const guint16 v);
-int aim_addtlvtochain32(aim_tlvlist_t **list, const guint16 type, const guint32 v);
-int aim_addtlvtochain_raw(aim_tlvlist_t **list, const guint16 t, const guint16 l, const guint8 *v);
-int aim_addtlvtochain_caps(aim_tlvlist_t **list, const guint16 t, const guint32 caps);
-int aim_addtlvtochain_noval(aim_tlvlist_t **list, const guint16 type);
-int aim_addtlvtochain_chatroom(aim_tlvlist_t **list, guint16 type, guint16 exchange, const char *roomname,
-                               guint16 instance);
-int aim_addtlvtochain_userinfo(aim_tlvlist_t **list, guint16 type, aim_userinfo_t *ui);
-int aim_addtlvtochain_frozentlvlist(aim_tlvlist_t **list, guint16 type, aim_tlvlist_t **tl);
-int aim_counttlvchain(aim_tlvlist_t **list);
-int aim_sizetlvchain(aim_tlvlist_t **list);
-
-
-/*
- * Get command from connections
- *
- * aim_get_commmand() is the libfaim lowlevel I/O in the receive direction.
- * XXX Make this easily overridable.
- *
- */
-int aim_get_command(aim_session_t *, aim_conn_t *);
-
-/*
- * Dispatch commands that are in the rx queue.
- */
-void aim_rxdispatch(aim_session_t *);
-
-int aim_debugconn_sendconnect(aim_session_t *sess, aim_conn_t *conn);
-
-typedef int (*aim_rxcallback_t)(aim_session_t *, aim_frame_t *, ...);
-
-struct aim_clientrelease {
-	char *name;
-	guint32 build;
-	char *url;
-	char *info;
-};
-
-struct aim_authresp_info {
-	char *sn;
-	guint16 errorcode;
-	char *errorurl;
-	guint16 regstatus;
-	char *email;
-	char *bosip;
-	guint8 *cookie;
-	struct aim_clientrelease latestrelease;
-	struct aim_clientrelease latestbeta;
-};
-
-/* Callback data for redirect. */
-struct aim_redirect_data {
-	guint16 group;
-	const char *ip;
-	const guint8 *cookie;
-	struct { /* group == AIM_CONN_TYPE_CHAT */
-		guint16 exchange;
-		const char *room;
-		guint16 instance;
-	} chat;
-};
-
-int aim_clientready(aim_session_t *sess, aim_conn_t *conn);
-int aim_sendflapver(aim_session_t *sess, aim_conn_t *conn);
-int aim_request_login(aim_session_t *sess, aim_conn_t *conn, const char *sn);
-int aim_send_login(aim_session_t *, aim_conn_t *, const char *, const char *, struct client_info_s *, const char *key);
-int aim_encode_password_md5(const char *password, const char *key, unsigned char *digest);
-void aim_purge_rxqueue(aim_session_t *);
-
-#define AIM_TX_QUEUED    0 /* default */
-#define AIM_TX_IMMEDIATE 1
-#define AIM_TX_USER      2
-int aim_tx_setenqueue(aim_session_t *sess, int what, int (*func)(aim_session_t *, aim_frame_t *));
-
-int aim_tx_flushqueue(aim_session_t *);
-void aim_tx_purgequeue(aim_session_t *);
-
-int aim_conn_setlatency(aim_conn_t *conn, int newval);
-
-void aim_conn_kill(aim_session_t *sess, aim_conn_t **deadconn);
-
-int aim_conn_addhandler(aim_session_t *, aim_conn_t *conn, u_short family, u_short type, aim_rxcallback_t newhandler,
-                        u_short flags);
-int aim_clearhandlers(aim_conn_t *conn);
-
-aim_conn_t *aim_conn_findbygroup(aim_session_t *sess, guint16 group);
-aim_session_t *aim_conn_getsess(aim_conn_t *conn);
-void aim_conn_close(aim_conn_t *deadconn);
-aim_conn_t *aim_newconn(aim_session_t *, int type, const char *dest);
-int aim_conngetmaxfd(aim_session_t *);
-aim_conn_t *aim_select(aim_session_t *, struct timeval *, int *);
-int aim_conn_isready(aim_conn_t *);
-int aim_conn_setstatus(aim_conn_t *, int);
-int aim_conn_completeconnect(aim_session_t *sess, aim_conn_t *conn);
-int aim_conn_isconnecting(aim_conn_t *conn);
-
-typedef void (*faim_debugging_callback_t)(aim_session_t *sess, int level, const char *format, va_list va);
-int aim_setdebuggingcb(aim_session_t * sess, faim_debugging_callback_t);
-void aim_session_init(aim_session_t *, guint32 flags, int debuglevel);
-void aim_session_kill(aim_session_t *);
-void aim_setupproxy(aim_session_t *sess, const char *server, const char *username, const char *password);
-aim_conn_t *aim_getconn_type(aim_session_t *, int type);
-aim_conn_t *aim_getconn_type_all(aim_session_t *, int type);
-aim_conn_t *aim_getconn_fd(aim_session_t *, int fd);
-
-/* aim_misc.c */
-
-
-struct aim_chat_roominfo {
-	unsigned short exchange;
-	char *name;
-	unsigned short instance;
-};
-
-struct aim_chat_invitation {
-	struct im_connection * ic;
-	char * name;
-	guint8 exchange;
-};
-
-#define AIM_VISIBILITYCHANGE_PERMITADD    0x05
-#define AIM_VISIBILITYCHANGE_PERMITREMOVE 0x06
-#define AIM_VISIBILITYCHANGE_DENYADD      0x07
-#define AIM_VISIBILITYCHANGE_DENYREMOVE   0x08
-
-#define AIM_PRIVFLAGS_ALLOWIDLE           0x01
-#define AIM_PRIVFLAGS_ALLOWMEMBERSINCE    0x02
-
-#define AIM_WARN_ANON                     0x01
-
-int aim_flap_nop(aim_session_t *sess, aim_conn_t *conn);
-int aim_bos_setprofile(aim_session_t *sess, aim_conn_t *conn, const char *profile, const char *awaymsg, guint32 caps);
-int aim_bos_setgroupperm(aim_session_t *, aim_conn_t *, guint32 mask);
-int aim_bos_setprivacyflags(aim_session_t *, aim_conn_t *, guint32);
-int aim_reqpersonalinfo(aim_session_t *, aim_conn_t *);
-int aim_reqservice(aim_session_t *, aim_conn_t *, guint16);
-int aim_bos_reqrights(aim_session_t *, aim_conn_t *);
-int aim_bos_reqbuddyrights(aim_session_t *, aim_conn_t *);
-int aim_bos_reqlocaterights(aim_session_t *, aim_conn_t *);
-int aim_setextstatus(aim_session_t *sess, aim_conn_t *conn, guint32 status);
-
-struct aim_fileheader_t *aim_getlisting(aim_session_t *sess, FILE *);
-
-#define AIM_CLIENTTYPE_UNKNOWN  0x0000
-#define AIM_CLIENTTYPE_MC       0x0001
-#define AIM_CLIENTTYPE_WINAIM   0x0002
-#define AIM_CLIENTTYPE_WINAIM41 0x0003
-#define AIM_CLIENTTYPE_AOL_TOC  0x0004
-
-#define AIM_RATE_CODE_CHANGE     0x0001
-#define AIM_RATE_CODE_WARNING    0x0002
-#define AIM_RATE_CODE_LIMIT      0x0003
-#define AIM_RATE_CODE_CLEARLIMIT 0x0004
-int aim_ads_requestads(aim_session_t *sess, aim_conn_t *conn);
-
-/* aim_im.c */
-
-aim_conn_t *aim_sendfile_initiate(aim_session_t *, const char *destsn, const char *filename, guint16 numfiles,
-                                  guint32 totsize);
-
-aim_conn_t *aim_getfile_initiate(aim_session_t *sess, aim_conn_t *conn, const char *destsn);
-int aim_oft_getfile_request(aim_session_t *sess, aim_conn_t *conn, const char *name, int size);
-int aim_oft_getfile_ack(aim_session_t *sess, aim_conn_t *conn);
-int aim_oft_getfile_end(aim_session_t *sess, aim_conn_t *conn);
-
-#define AIM_SENDMEMBLOCK_FLAG_ISREQUEST  0
-#define AIM_SENDMEMBLOCK_FLAG_ISHASH     1
-
-#define AIM_GETINFO_GENERALINFO 0x00001
-#define AIM_GETINFO_AWAYMESSAGE 0x00003
-#define AIM_GETINFO_CAPABILITIES 0x0004
-
-struct aim_invite_priv {
-	char *sn;
-	char *roomname;
-	guint16 exchange;
-	guint16 instance;
-};
-
-#define AIM_COOKIETYPE_UNKNOWN  0x00
-#define AIM_COOKIETYPE_ICBM     0x01
-#define AIM_COOKIETYPE_ADS      0x02
-#define AIM_COOKIETYPE_BOS      0x03
-#define AIM_COOKIETYPE_IM       0x04
-#define AIM_COOKIETYPE_CHAT     0x05
-#define AIM_COOKIETYPE_CHATNAV  0x06
-#define AIM_COOKIETYPE_INVITE   0x07
-
-int aim_handlerendconnect(aim_session_t *sess, aim_conn_t *cur);
-
-#define AIM_TRANSFER_DENY_NOTSUPPORTED 0x0000
-#define AIM_TRANSFER_DENY_DECLINE 0x0001
-#define AIM_TRANSFER_DENY_NOTACCEPTING 0x0002
-aim_conn_t *aim_accepttransfer(aim_session_t *sess, aim_conn_t *conn, const char *sn, const guint8 *cookie,
-                               const guint8 *ip, guint16 listingfiles, guint16 listingtotsize, guint16 listingsize,
-                               guint32 listingchecksum, guint16 rendid);
-
-int aim_getinfo(aim_session_t *, aim_conn_t *, const char *, unsigned short);
-
-#define AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED       0x00000001
-#define AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED    0x00000002
-
-/* This is what the server will give you if you don't set them yourself. */
-#define AIM_IMPARAM_DEFAULTS { \
-		0, \
-		AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED | AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED, \
-		512, /* !! Note how small this is. */ \
-		(99.9) * 10, (99.9) * 10, \
-		1000 /* !! And how large this is. */ \
-}
-
-/* This is what most AIM versions use. */
-#define AIM_IMPARAM_REASONABLE { \
-		0, \
-		AIM_IMPARAM_FLAG_CHANMSGS_ALLOWED | AIM_IMPARAM_FLAG_MISSEDCALLS_ENABLED, \
-		8000, \
-		(99.9) * 10, (99.9) * 10, \
-		0 \
-}
-
-
-struct aim_icbmparameters {
-	guint16 maxchan;
-	guint32 flags; /* AIM_IMPARAM_FLAG_ */
-	guint16 maxmsglen; /* message size that you will accept */
-	guint16 maxsenderwarn; /* this and below are *10 (999=99.9%) */
-	guint16 maxrecverwarn;
-	guint32 minmsginterval; /* in milliseconds? */
-};
-
-int aim_reqicbmparams(aim_session_t *sess);
-int aim_seticbmparam(aim_session_t *sess, struct aim_icbmparameters *params);
-
-/* auth.c */
-int aim_sendcookie(aim_session_t *, aim_conn_t *, const guint8 *);
-
-int aim_admin_changepasswd(aim_session_t *, aim_conn_t *, const char *newpw, const char *curpw);
-int aim_admin_reqconfirm(aim_session_t *sess, aim_conn_t *conn);
-int aim_admin_getinfo(aim_session_t *sess, aim_conn_t *conn, guint16 info);
-int aim_admin_setemail(aim_session_t *sess, aim_conn_t *conn, const char *newemail);
-int aim_admin_setnick(aim_session_t *sess, aim_conn_t *conn, const char *newnick);
-
-/* These apply to exchanges as well. */
-#define AIM_CHATROOM_FLAG_EVILABLE 0x0001
-#define AIM_CHATROOM_FLAG_NAV_ONLY 0x0002
-#define AIM_CHATROOM_FLAG_INSTANCING_ALLOWED 0x0004
-#define AIM_CHATROOM_FLAG_OCCUPANT_PEEK_ALLOWED 0x0008
-
-struct aim_chat_exchangeinfo {
-	guint16 number;
-	guint16 flags;
-	char *name;
-	char *charset1;
-	char *lang1;
-	char *charset2;
-	char *lang2;
-};
-
-#define AIM_CHATFLAGS_NOREFLECT         0x0001
-#define AIM_CHATFLAGS_AWAY              0x0002
-#define AIM_CHATFLAGS_UNICODE           0x0004
-#define AIM_CHATFLAGS_ISO_8859_1        0x0008
-
-int aim_chat_send_im(aim_session_t *sess, aim_conn_t *conn, guint16 flags, const char *msg, int msglen);
-int aim_chat_join(aim_session_t *sess, aim_conn_t *conn, guint16 exchange, const char *roomname, guint16 instance);
-
-int aim_chatnav_reqrights(aim_session_t *sess, aim_conn_t *conn);
-
-int aim_chat_invite(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *msg, guint16 exchange,
-                    const char *roomname, guint16 instance);
-
-int aim_chatnav_createroom(aim_session_t *sess, aim_conn_t *conn, const char *name, guint16 exchange);
-
-/* aim_util.c */
-/*
- * These are really ugly.  You'd think this was LISP.  I wish it was.
- *
- * XXX With the advent of bstream's, these should be removed to enforce
- * their use.
- *
- */
-#define aimutil_put8(buf, data) ((*(buf) = (u_char) (data) & 0xff), 1)
-#define aimutil_get8(buf) ((*(buf)) & 0xff)
-#define aimutil_put16(buf, data) ( \
-	        (*(buf) = (u_char) ((data) >> 8) & 0xff), \
-	        (*((buf) + 1) = (u_char) (data) & 0xff),  \
-	        2)
-#define aimutil_get16(buf) ((((*(buf)) << 8) & 0xff00) + ((*((buf) + 1)) & 0xff))
-#define aimutil_put32(buf, data) ( \
-	        (*((buf)) = (u_char) ((data) >> 24) & 0xff), \
-	        (*((buf) + 1) = (u_char) ((data) >> 16) & 0xff), \
-	        (*((buf) + 2) = (u_char) ((data) >> 8) & 0xff), \
-	        (*((buf) + 3) = (u_char) (data) & 0xff), \
-	        4)
-#define aimutil_get32(buf) ((((*(buf)) << 24) & 0xff000000) + \
-	                    (((*((buf) + 1)) << 16) & 0x00ff0000) + \
-	                    (((*((buf) + 2)) << 8) & 0x0000ff00) + \
-	                    (((*((buf) + 3)) & 0x000000ff)))
-
-/* Little-endian versions (damn ICQ) */
-#define aimutil_putle8(buf, data) ( \
-	        (*(buf) = (unsigned char) (data) & 0xff), \
-	        1)
-#define aimutil_getle8(buf) ( \
-	        (*(buf)) & 0xff \
-	        )
-#define aimutil_putle16(buf, data) ( \
-	        (*((buf) + 0) = (unsigned char) ((data) >> 0) & 0xff),  \
-	        (*((buf) + 1) = (unsigned char) ((data) >> 8) & 0xff), \
-	        2)
-#define aimutil_getle16(buf) ( \
-	        (((*((buf) + 0)) << 0) & 0x00ff) + \
-	        (((*((buf) + 1)) << 8) & 0xff00) \
-	        )
-#define aimutil_putle32(buf, data) ( \
-	        (*((buf) + 0) = (unsigned char) ((data) >>  0) & 0xff), \
-	        (*((buf) + 1) = (unsigned char) ((data) >>  8) & 0xff), \
-	        (*((buf) + 2) = (unsigned char) ((data) >> 16) & 0xff), \
-	        (*((buf) + 3) = (unsigned char) ((data) >> 24) & 0xff), \
-	        4)
-#define aimutil_getle32(buf) ( \
-	        (((*((buf) + 0)) <<  0) & 0x000000ff) + \
-	        (((*((buf) + 1)) <<  8) & 0x0000ff00) + \
-	        (((*((buf) + 2)) << 16) & 0x00ff0000) + \
-	        (((*((buf) + 3)) << 24) & 0xff000000))
-
-
-int aim_sncmp(const char *a, const char *b);
-
-#include <aim_internal.h>
-
-/*
- * SNAC Families.
- */
-#define AIM_CB_FAM_ACK 0x0000
-#define AIM_CB_FAM_GEN 0x0001
-#define AIM_CB_FAM_SPECIAL 0xffff /* Internal libfaim use */
-
-/*
- * SNAC Family: Ack.
- *
- * Not really a family, but treating it as one really
- * helps it fit into the libfaim callback structure better.
- *
- */
-#define AIM_CB_ACK_ACK 0x0001
-
-/*
- * SNAC Family: General.
- */
-#define AIM_CB_GEN_ERROR 0x0001
-#define AIM_CB_GEN_CLIENTREADY 0x0002
-#define AIM_CB_GEN_SERVERREADY 0x0003
-#define AIM_CB_GEN_SERVICEREQ 0x0004
-#define AIM_CB_GEN_REDIRECT 0x0005
-#define AIM_CB_GEN_RATEINFOREQ 0x0006
-#define AIM_CB_GEN_RATEINFO 0x0007
-#define AIM_CB_GEN_RATEINFOACK 0x0008
-#define AIM_CB_GEN_RATECHANGE 0x000a
-#define AIM_CB_GEN_SERVERPAUSE 0x000b
-#define AIM_CB_GEN_SERVERRESUME 0x000d
-#define AIM_CB_GEN_REQSELFINFO 0x000e
-#define AIM_CB_GEN_SELFINFO 0x000f
-#define AIM_CB_GEN_EVIL 0x0010
-#define AIM_CB_GEN_SETIDLE 0x0011
-#define AIM_CB_GEN_MIGRATIONREQ 0x0012
-#define AIM_CB_GEN_MOTD 0x0013
-#define AIM_CB_GEN_SETPRIVFLAGS 0x0014
-#define AIM_CB_GEN_WELLKNOWNURL 0x0015
-#define AIM_CB_GEN_NOP 0x0016
-#define AIM_CB_GEN_DEFAULT 0xffff
-
-/*
- * SNAC Family: Advertisement Services
- */
-#define AIM_CB_ADS_ERROR 0x0001
-#define AIM_CB_ADS_DEFAULT 0xffff
-
-/*
- * OFT Services
- *
- * See non-SNAC note below.
- */
-#define AIM_CB_OFT_DIRECTIMCONNECTREQ 0x0001 /* connect request -- actually an OSCAR CAP*/
-#define AIM_CB_OFT_DIRECTIMINCOMING 0x0002
-#define AIM_CB_OFT_DIRECTIMDISCONNECT 0x0003
-#define AIM_CB_OFT_DIRECTIMTYPING 0x0004
-#define AIM_CB_OFT_DIRECTIMINITIATE 0x0005
-
-#define AIM_CB_OFT_GETFILECONNECTREQ 0x0006 /* connect request -- actually an OSCAR CAP*/
-#define AIM_CB_OFT_GETFILELISTINGREQ 0x0007 /* OFT listing.txt request */
-#define AIM_CB_OFT_GETFILEFILEREQ 0x0008    /* received file request */
-#define AIM_CB_OFT_GETFILEFILESEND 0x0009   /* received file request confirm -- send data */
-#define AIM_CB_OFT_GETFILECOMPLETE 0x000a   /* received file send complete*/
-#define AIM_CB_OFT_GETFILEINITIATE 0x000b   /* request for file get acknowledge */
-#define AIM_CB_OFT_GETFILEDISCONNECT 0x000c   /* OFT connection disconnected.*/
-#define AIM_CB_OFT_GETFILELISTING 0x000d   /* OFT listing.txt received.*/
-#define AIM_CB_OFT_GETFILERECEIVE 0x000e   /* OFT file incoming.*/
-#define AIM_CB_OFT_GETFILELISTINGRXCONFIRM 0x000f
-#define AIM_CB_OFT_GETFILESTATE4 0x0010
-
-#define AIM_CB_OFT_SENDFILEDISCONNECT 0x0020   /* OFT connection disconnected.*/
-
-
-
-/*
- * SNAC Family: Internal Messages
- *
- * This isn't truly a SNAC family either, but using
- * these, we can integrated non-SNAC services into
- * the SNAC-centered libfaim callback structure.
- *
- */
-#define AIM_CB_SPECIAL_AUTHSUCCESS 0x0001
-#define AIM_CB_SPECIAL_AUTHOTHER 0x0002
-#define AIM_CB_SPECIAL_CONNERR 0x0003
-#define AIM_CB_SPECIAL_CONNCOMPLETE 0x0004
-#define AIM_CB_SPECIAL_FLAPVER 0x0005
-#define AIM_CB_SPECIAL_CONNINITDONE 0x0006
-#define AIM_CB_SPECIAL_IMAGETRANSFER 0x007
-#define AIM_CB_SPECIAL_UNKNOWN 0xffff
-#define AIM_CB_SPECIAL_DEFAULT AIM_CB_SPECIAL_UNKNOWN
-
-#endif /* __AIM_H__ */
Index: protocols/oscar/aim_internal.h
===================================================================
--- protocols/oscar/aim_internal.h	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,209 +1,0 @@
-/*
- * aim_internal.h -- prototypes/structs for the guts of libfaim
- *
- */
-
-#ifndef __AIM_INTERNAL_H__
-#define __AIM_INTERNAL_H__ 1
-
-typedef struct {
-	guint16 family;
-	guint16 subtype;
-	guint16 flags;
-	guint32 id;
-} aim_modsnac_t;
-
-#define AIM_MODULENAME_MAXLEN 16
-#define AIM_MODFLAG_MULTIFAMILY 0x0001
-typedef struct aim_module_s {
-	guint16 family;
-	guint16 version;
-	guint16 toolid;
-	guint16 toolversion;
-	guint16 flags;
-	char name[AIM_MODULENAME_MAXLEN + 1];
-	int (*snachandler)(aim_session_t *sess, struct aim_module_s *mod, aim_frame_t *rx, aim_modsnac_t *snac,
-	                   aim_bstream_t *bs);
-	void (*shutdown)(aim_session_t *sess, struct aim_module_s *mod);
-	void *priv;
-	struct aim_module_s *next;
-} aim_module_t;
-
-int aim__registermodule(aim_session_t *sess, int (*modfirst)(aim_session_t *, aim_module_t *));
-void aim__shutdownmodules(aim_session_t *sess);
-aim_module_t *aim__findmodulebygroup(aim_session_t *sess, guint16 group);
-
-int buddylist_modfirst(aim_session_t *sess, aim_module_t *mod);
-int admin_modfirst(aim_session_t *sess, aim_module_t *mod);
-int bos_modfirst(aim_session_t *sess, aim_module_t *mod);
-int search_modfirst(aim_session_t *sess, aim_module_t *mod);
-int stats_modfirst(aim_session_t *sess, aim_module_t *mod);
-int auth_modfirst(aim_session_t *sess, aim_module_t *mod);
-int msg_modfirst(aim_session_t *sess, aim_module_t *mod);
-int misc_modfirst(aim_session_t *sess, aim_module_t *mod);
-int chatnav_modfirst(aim_session_t *sess, aim_module_t *mod);
-int chat_modfirst(aim_session_t *sess, aim_module_t *mod);
-int locate_modfirst(aim_session_t *sess, aim_module_t *mod);
-int general_modfirst(aim_session_t *sess, aim_module_t *mod);
-int ssi_modfirst(aim_session_t *sess, aim_module_t *mod);
-int icq_modfirst(aim_session_t *sess, aim_module_t *mod);
-
-int aim_genericreq_n(aim_session_t *, aim_conn_t *conn, guint16 family, guint16 subtype);
-int aim_genericreq_n_snacid(aim_session_t *, aim_conn_t *conn, guint16 family, guint16 subtype);
-int aim_genericreq_l(aim_session_t *, aim_conn_t *conn, guint16 family, guint16 subtype, guint32 *);
-int aim_genericreq_s(aim_session_t *, aim_conn_t *conn, guint16 family, guint16 subtype, guint16 *);
-
-#define AIMBS_CURPOSPAIR(x) ((x)->data + (x)->offset), ((x)->len - (x)->offset)
-
-void aim_rxqueue_cleanbyconn(aim_session_t *sess, aim_conn_t *conn);
-int aim_recv(int fd, void *buf, size_t count);
-int aim_bstream_init(aim_bstream_t *bs, guint8 *data, int len);
-int aim_bstream_empty(aim_bstream_t *bs);
-int aim_bstream_curpos(aim_bstream_t *bs);
-int aim_bstream_setpos(aim_bstream_t *bs, int off);
-void aim_bstream_rewind(aim_bstream_t *bs);
-int aim_bstream_advance(aim_bstream_t *bs, int n);
-guint8 aimbs_get8(aim_bstream_t *bs);
-guint16 aimbs_get16(aim_bstream_t *bs);
-guint32 aimbs_get32(aim_bstream_t *bs);
-guint8 aimbs_getle8(aim_bstream_t *bs);
-guint16 aimbs_getle16(aim_bstream_t *bs);
-guint32 aimbs_getle32(aim_bstream_t *bs);
-int aimbs_put8(aim_bstream_t *bs, guint8 v);
-int aimbs_put16(aim_bstream_t *bs, guint16 v);
-int aimbs_put32(aim_bstream_t *bs, guint32 v);
-int aimbs_putle8(aim_bstream_t *bs, guint8 v);
-int aimbs_putle16(aim_bstream_t *bs, guint16 v);
-int aimbs_putle32(aim_bstream_t *bs, guint32 v);
-int aimbs_getrawbuf(aim_bstream_t *bs, guint8 *buf, int len);
-guint8 *aimbs_getraw(aim_bstream_t *bs, int len);
-char *aimbs_getstr(aim_bstream_t *bs, int len);
-int aimbs_putraw(aim_bstream_t *bs, const guint8 *v, int len);
-int aimbs_putbs(aim_bstream_t *bs, aim_bstream_t *srcbs, int len);
-
-int aim_get_command_rendezvous(aim_session_t *sess, aim_conn_t *conn);
-
-int aim_tx_sendframe(aim_session_t *sess, aim_frame_t *cur);
-flap_seqnum_t aim_get_next_txseqnum(aim_conn_t *);
-aim_frame_t *aim_tx_new(aim_session_t *sess, aim_conn_t *conn, guint8 framing, guint8 chan, int datalen);
-void aim_frame_destroy(aim_frame_t *);
-int aim_tx_enqueue(aim_session_t *, aim_frame_t *);
-int aim_tx_printqueue(aim_session_t *);
-void aim_tx_cleanqueue(aim_session_t *, aim_conn_t *);
-
-aim_rxcallback_t aim_callhandler(aim_session_t *sess, aim_conn_t *conn, u_short family, u_short type);
-
-/*
- * Generic SNAC structure.  Rarely if ever used.
- */
-typedef struct aim_snac_s {
-	aim_snacid_t id;
-	guint16 family;
-	guint16 type;
-	guint16 flags;
-	void *data;
-	time_t issuetime;
-	struct aim_snac_s *next;
-} aim_snac_t;
-
-void aim_initsnachash(aim_session_t *sess);
-aim_snacid_t aim_cachesnac(aim_session_t *sess, const guint16 family, const guint16 type, const guint16 flags,
-                           const void *data, const int datalen);
-aim_snac_t *aim_remsnac(aim_session_t *, aim_snacid_t id);
-void aim_cleansnacs(aim_session_t *, int maxage);
-int aim_putsnac(aim_bstream_t *, guint16 family, guint16 type, guint16 flags, aim_snacid_t id);
-
-int aim_oft_buildheader(unsigned char *, struct aim_fileheader_t *);
-
-int aim_parse_unknown(aim_session_t *, aim_frame_t *, ...);
-
-/* Stored in ->priv of the service request SNAC for chats. */
-struct chatsnacinfo {
-	guint16 exchange;
-	char name[128];
-	guint16 instance;
-};
-
-/* these are used by aim_*_clientready */
-#define AIM_TOOL_JAVA   0x0001
-#define AIM_TOOL_MAC    0x0002
-#define AIM_TOOL_WIN16  0x0003
-#define AIM_TOOL_WIN32  0x0004
-#define AIM_TOOL_MAC68K 0x0005
-#define AIM_TOOL_MACPPC 0x0006
-#define AIM_TOOL_NEWWIN 0x0010
-struct aim_tool_version {
-	guint16 group;
-	guint16 version;
-	guint16 tool;
-	guint16 toolversion;
-};
-
-/*
- * In SNACland, the terms 'family' and 'group' are synonymous -- the former
- * is my term, the latter is AOL's.
- */
-struct snacgroup {
-	guint16 group;
-	struct snacgroup *next;
-};
-
-struct snacpair {
-	guint16 group;
-	guint16 subtype;
-	struct snacpair *next;
-};
-
-struct rateclass {
-	guint16 classid;
-	guint32 windowsize;
-	guint32 clear;
-	guint32 alert;
-	guint32 limit;
-	guint32 disconnect;
-	guint32 current;
-	guint32 max;
-	guint8 unknown[5]; /* only present in versions >= 3 */
-	struct snacpair *members;
-	struct rateclass *next;
-};
-
-/*
- * This is inside every connection.  But it is a void * to anything
- * outside of libfaim.  It should remain that way.  It's called data
- * abstraction.  Maybe you've heard of it.  (Probably not if you're a
- * libfaim user.)
- *
- */
-typedef struct aim_conn_inside_s {
-	struct snacgroup *groups;
-	struct rateclass *rates;
-} aim_conn_inside_t;
-
-void aim_conn_addgroup(aim_conn_t *conn, guint16 group);
-
-guint32 aim_getcap(aim_session_t *sess, aim_bstream_t *bs, int len);
-int aim_putcap(aim_bstream_t *bs, guint32 caps);
-
-int aim_cachecookie(aim_session_t *sess, aim_msgcookie_t *cookie);
-aim_msgcookie_t *aim_uncachecookie(aim_session_t *sess, guint8 *cookie, int type);
-aim_msgcookie_t *aim_mkcookie(guint8 *, int, void *);
-aim_msgcookie_t *aim_checkcookie(aim_session_t *sess, const unsigned char *, const int);
-int aim_freecookie(aim_session_t *sess, aim_msgcookie_t *cookie);
-int aim_cookie_free(aim_session_t *sess, aim_msgcookie_t *cookie);
-
-int aim_extractuserinfo(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t *);
-
-int aim_chat_readroominfo(aim_bstream_t *bs, struct aim_chat_roominfo *outinfo);
-
-void aim_conn_close_rend(aim_session_t *sess, aim_conn_t *conn);
-void aim_conn_kill_rend(aim_session_t *sess, aim_conn_t *conn);
-
-void aim_conn_kill_chat(aim_session_t *sess, aim_conn_t *conn);
-
-/* These are all handled internally now. */
-int aim_setversions(aim_session_t *sess, aim_conn_t *conn);
-int aim_reqrates(aim_session_t *, aim_conn_t *);
-int aim_rates_addparam(aim_session_t *, aim_conn_t *);
-
-#endif /* __AIM_INTERNAL_H__ */
Index: protocols/oscar/aim_prefixes.h
===================================================================
--- protocols/oscar/aim_prefixes.h	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,93 +1,0 @@
-/* Automatically generated prefixes to avoid symbol conflicts with libpurple.
- * Because sometimes people compile both oscar and purple and things break.
- * This is awful but i know no better solution other than not running libpurple in the same process.
- *
- * Made with the following commands:
- *
- * nm --defined-only oscar_mod.o | awk '{print $3}' | sort | uniq > bee_syms
- * nm --defined-only liboscar.so | awk '{print $3}' | sort | uniq > purple_syms
- * comm -12 bee_syms purple_syms | sed 's/^.*$/#define & b_&/' > aim_prefixes.h
- */
-
-#define admin_modfirst b_admin_modfirst
-#define aim_admin_changepasswd b_aim_admin_changepasswd
-#define aim_admin_getinfo b_aim_admin_getinfo
-#define aim_admin_reqconfirm b_aim_admin_reqconfirm
-#define aim_admin_setemail b_aim_admin_setemail
-#define aim_admin_setnick b_aim_admin_setnick
-#define aim_bos_reqrights b_aim_bos_reqrights
-#define aim_cachecookie b_aim_cachecookie
-#define aim_cachesnac b_aim_cachesnac
-#define aim_callhandler b_aim_callhandler
-#define aim_caps b_aim_caps
-#define aim_chat_join b_aim_chat_join
-#define aim_chatnav_createroom b_aim_chatnav_createroom
-#define aim_chatnav_reqrights b_aim_chatnav_reqrights
-#define aim_chat_readroominfo b_aim_chat_readroominfo
-#define aim_chat_send_im b_aim_chat_send_im
-#define aim_checkcookie b_aim_checkcookie
-#define aim_cleansnacs b_aim_cleansnacs
-#define aim_cookie_free b_aim_cookie_free
-#define aim__findmodule b_aim__findmodule
-#define aim__findmodulebygroup b_aim__findmodulebygroup
-#define aim_genericreq_l b_aim_genericreq_l
-#define aim_genericreq_n b_aim_genericreq_n
-#define aim_genericreq_n_snacid b_aim_genericreq_n_snacid
-#define aim_icq_freeinfo b_aim_icq_freeinfo
-#define aim_icq_getallinfo b_aim_icq_getallinfo
-#define aim_im_sendmtn b_aim_im_sendmtn
-#define aim_initsnachash b_aim_initsnachash
-#define aim_mkcookie b_aim_mkcookie
-#define aim_newsnac b_aim_newsnac
-#define aim_putsnac b_aim_putsnac
-#define aim__registermodule b_aim__registermodule
-#define aim_remsnac b_aim_remsnac
-#define aim_request_login b_aim_request_login
-#define aim_send_login b_aim_send_login
-#define aim__shutdownmodules b_aim__shutdownmodules
-#define aim_ssi_enable b_aim_ssi_enable
-#define aim_ssi_freelist b_aim_ssi_freelist
-#define aim_ssi_getpermdeny b_aim_ssi_getpermdeny
-#define aim_ssi_itemlist_add b_aim_ssi_itemlist_add
-#define aim_ssi_itemlist_find b_aim_ssi_itemlist_find
-#define aim_ssi_itemlist_finditem b_aim_ssi_itemlist_finditem
-#define aim_ssi_itemlist_rebuildgroup b_aim_ssi_itemlist_rebuildgroup
-#define aim_ssi_modbegin b_aim_ssi_modbegin
-#define aim_ssi_modend b_aim_ssi_modend
-#define aim_ssi_movebuddy b_aim_ssi_movebuddy
-#define aim_ssi_reqrights b_aim_ssi_reqrights
-#define aim_uncachecookie b_aim_uncachecookie
-#define auth_modfirst b_auth_modfirst
-#define bos_modfirst b_bos_modfirst
-#define buddylist_modfirst b_buddylist_modfirst
-#define chat_modfirst b_chat_modfirst
-#define chatnav_modfirst b_chatnav_modfirst
-#define extract_name b_extract_name
-#define icq_modfirst b_icq_modfirst
-#define incomingim b_incomingim
-#define incomingim_ch2_chat_free b_incomingim_ch2_chat_free
-#define incomingim_ch2_icqserverrelay_free b_incomingim_ch2_icqserverrelay_free
-#define locate_modfirst b_locate_modfirst
-#define misc_modfirst b_misc_modfirst
-#define msgerrreason b_msgerrreason
-#define msg_modfirst b_msg_modfirst
-#define oscar_add_buddy b_oscar_add_buddy
-#define oscar_add_deny b_oscar_add_deny
-#define oscar_add_permit b_oscar_add_permit
-#define oscar_chat_invite b_oscar_chat_invite
-#define oscar_chat_kill b_oscar_chat_kill
-#define oscar_chat_leave b_oscar_chat_leave
-#define oscar_encoding_to_utf8 b_oscar_encoding_to_utf8
-#define oscar_get_info b_oscar_get_info
-#define oscar_init b_oscar_init
-#define oscar_keepalive b_oscar_keepalive
-#define oscar_login b_oscar_login
-#define oscar_rem_deny b_oscar_rem_deny
-#define oscar_remove_buddy b_oscar_remove_buddy
-#define oscar_rem_permit b_oscar_rem_permit
-#define oscar_send_typing b_oscar_send_typing
-#define search_modfirst b_search_modfirst
-#define snachandler b_snachandler
-#define ssi_modfirst b_ssi_modfirst
-#define ssi_shutdown b_ssi_shutdown
-#define stats_modfirst b_stats_modfirst
Index: protocols/oscar/auth.c
===================================================================
--- protocols/oscar/auth.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,421 +1,0 @@
-/*
- * Deals with the authorizer (group 0x0017=23, and old-style non-SNAC login).
- *
- */
-
-#include <aim.h>
-
-#include "md5.h"
-
-/*
- * This just pushes the passed cookie onto the passed connection, without
- * the SNAC header or any of that.
- *
- * Very commonly used, as every connection except auth will require this to
- * be the first thing you send.
- *
- */
-int aim_sendcookie(aim_session_t *sess, aim_conn_t *conn, const guint8 *chipsahoy)
-{
-	aim_frame_t *fr;
-	aim_tlvlist_t *tl = NULL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x0001, 4 + 2 + 2 + AIM_COOKIELEN))) {
-		return -ENOMEM;
-	}
-
-	aimbs_put32(&fr->data, 0x00000001);
-	aim_addtlvtochain_raw(&tl, 0x0006, AIM_COOKIELEN, chipsahoy);
-	aim_writetlvchain(&fr->data, &tl);
-	aim_freetlvchain(&tl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Normally the FLAP version is sent as the first few bytes of the cookie,
- * meaning you generally never call this.
- *
- * But there are times when something might want it separate. Specifically,
- * libfaim sends this internally when doing SNAC login.
- *
- */
-int aim_sendflapver(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_frame_t *fr;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x01, 4))) {
-		return -ENOMEM;
-	}
-
-	aimbs_put32(&fr->data, 0x00000001);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * In AIM 3.5 protocol, the first stage of login is to request login from the
- * Authorizer, passing it the screen name for verification.  If the name is
- * invalid, a 0017/0003 is spit back, with the standard error contents.  If
- * valid, a 0017/0007 comes back, which is the signal to send it the main
- * login command (0017/0002).
- *
- */
-int aim_request_login(aim_session_t *sess, aim_conn_t *conn, const char *sn)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
-
-	if (!sess || !conn || !sn) {
-		return -EINVAL;
-	}
-
-	sess->flags |= AIM_SESS_FLAGS_SNACLOGIN;
-
-	aim_sendflapver(sess, conn);
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 2 + 2 + strlen(sn)))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, 0x0017, 0x0006, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0017, 0x0006, 0x0000, snacid);
-
-	aim_addtlvtochain_raw(&tl, 0x0001, strlen(sn), (guint8 *) sn);
-	aim_writetlvchain(&fr->data, &tl);
-	aim_freetlvchain(&tl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * send_login(int socket, char *sn, char *password)
- *
- * This is the initial login request packet.
- *
- * NOTE!! If you want/need to make use of the aim_sendmemblock() function,
- * then the client information you send here must exactly match the
- * executable that you're pulling the data from.
- *
- * WinAIM 4.8.2540
- *   clientstring = "AOL Instant Messenger (SM), version 4.8.2540/WIN32"
- *   clientid = 0x0109
- *   major = 0x0004
- *   minor = 0x0008
- *   point = 0x0000
- *   build = 0x09ec
- *   t(0x0014) = 0x000000af
- *   t(0x004a) = 0x01
- *
- * WinAIM 4.3.2188:
- *   clientstring = "AOL Instant Messenger (SM), version 4.3.2188/WIN32"
- *   clientid = 0x0109
- *   major = 0x0400
- *   minor = 0x0003
- *   point = 0x0000
- *   build = 0x088c
- *   unknown = 0x00000086
- *   lang = "en"
- *   country = "us"
- *   unknown4a = 0x01
- *
- * Latest WinAIM that libfaim can emulate without server-side buddylists:
- *   clientstring = "AOL Instant Messenger (SM), version 4.1.2010/WIN32"
- *   clientid = 0x0004
- *   major  = 0x0004
- *   minor  = 0x0001
- *   point = 0x0000
- *   build  = 0x07da
- *   unknown= 0x0000004b
- *
- * WinAIM 3.5.1670:
- *   clientstring = "AOL Instant Messenger (SM), version 3.5.1670/WIN32"
- *   clientid = 0x0004
- *   major =  0x0003
- *   minor =  0x0005
- *   point = 0x0000
- *   build =  0x0686
- *   unknown =0x0000002a
- *
- * Java AIM 1.1.19:
- *   clientstring = "AOL Instant Messenger (TM) version 1.1.19 for Java built 03/24/98, freeMem 215871 totalMem 1048567, i686, Linus, #2 SMP Sun Feb 11 03:41:17 UTC 2001 2.4.1-ac9, IBM Corporation, 1.1.8, 45.3, Tue Mar 27 12:09:17 PST 2001"
- *   clientid = 0x0001
- *   major  = 0x0001
- *   minor  = 0x0001
- *   point = (not sent)
- *   build  = 0x0013
- *   unknown= (not sent)
- *
- * AIM for Linux 1.1.112:
- *   clientstring = "AOL Instant Messenger (SM)"
- *   clientid = 0x1d09
- *   major  = 0x0001
- *   minor  = 0x0001
- *   point = 0x0001
- *   build  = 0x0070
- *   unknown= 0x0000008b
- *   serverstore = 0x01
- *
- */
-int aim_send_login(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *password,
-                   struct client_info_s *ci, const char *key)
-{
-	aim_frame_t *fr;
-	aim_tlvlist_t *tl = NULL;
-	guint8 digest[16];
-	aim_snacid_t snacid;
-
-	if (!ci || !sn || !password) {
-		return -EINVAL;
-	}
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, 0x0017, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0017, 0x0002, 0x0000, snacid);
-
-	aim_addtlvtochain_raw(&tl, 0x0001, strlen(sn), (guint8 *) sn);
-
-	aim_encode_password_md5(password, key, digest);
-	aim_addtlvtochain_raw(&tl, 0x0025, 16, digest);
-
-	/*
-	 * Newer versions of winaim have an empty type x004c TLV here.
-	 */
-
-	if (ci->clientstring) {
-		aim_addtlvtochain_raw(&tl, 0x0003, strlen(ci->clientstring), (guint8 *) ci->clientstring);
-	}
-	aim_addtlvtochain16(&tl, 0x0016, (guint16) ci->clientid);
-	aim_addtlvtochain16(&tl, 0x0017, (guint16) ci->major);
-	aim_addtlvtochain16(&tl, 0x0018, (guint16) ci->minor);
-	aim_addtlvtochain16(&tl, 0x0019, (guint16) ci->point);
-	aim_addtlvtochain16(&tl, 0x001a, (guint16) ci->build);
-	aim_addtlvtochain_raw(&tl, 0x000e, strlen(ci->country), (guint8 *) ci->country);
-	aim_addtlvtochain_raw(&tl, 0x000f, strlen(ci->lang), (guint8 *) ci->lang);
-
-	/*
-	 * If set, old-fashioned buddy lists will not work. You will need
-	 * to use SSI.
-	 */
-	aim_addtlvtochain8(&tl, 0x004a, 0x01);
-
-	aim_writetlvchain(&fr->data, &tl);
-
-	aim_freetlvchain(&tl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-int aim_encode_password_md5(const char *password, const char *key, guint8 *digest)
-{
-	md5_state_t state;
-
-	md5_init(&state);
-	md5_append(&state, (const md5_byte_t *) key, strlen(key));
-	md5_append(&state, (const md5_byte_t *) password, strlen(password));
-	md5_append(&state, (const md5_byte_t *) AIM_MD5_STRING, strlen(AIM_MD5_STRING));
-	md5_finish(&state, (md5_byte_t *) digest);
-
-	return 0;
-}
-
-/*
- * This is sent back as a general response to the login command.
- * It can be either an error or a success, depending on the
- * precense of certain TLVs.
- *
- * The client should check the value passed as errorcode. If
- * its nonzero, there was an error.
- *
- */
-static int parse(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_tlvlist_t *tlvlist;
-	aim_rxcallback_t userfunc;
-	struct aim_authresp_info info;
-	int ret = 0;
-
-	memset(&info, 0, sizeof(info));
-
-	/*
-	 * Read block of TLVs.  All further data is derived
-	 * from what is parsed here.
-	 */
-	tlvlist = aim_readtlvchain(bs);
-
-	/*
-	 * No matter what, we should have a screen name.
-	 */
-	memset(sess->sn, 0, sizeof(sess->sn));
-	if (aim_gettlv(tlvlist, 0x0001, 1)) {
-		info.sn = aim_gettlv_str(tlvlist, 0x0001, 1);
-		strncpy(sess->sn, info.sn, sizeof(sess->sn));
-	}
-
-	/*
-	 * Check for an error code.  If so, we should also
-	 * have an error url.
-	 */
-	if (aim_gettlv(tlvlist, 0x0008, 1)) {
-		info.errorcode = aim_gettlv16(tlvlist, 0x0008, 1);
-	}
-	if (aim_gettlv(tlvlist, 0x0004, 1)) {
-		info.errorurl = aim_gettlv_str(tlvlist, 0x0004, 1);
-	}
-
-	/*
-	 * BOS server address.
-	 */
-	if (aim_gettlv(tlvlist, 0x0005, 1)) {
-		info.bosip = aim_gettlv_str(tlvlist, 0x0005, 1);
-	}
-
-	/*
-	 * Authorization cookie.
-	 */
-	if (aim_gettlv(tlvlist, 0x0006, 1)) {
-		aim_tlv_t *tmptlv;
-
-		tmptlv = aim_gettlv(tlvlist, 0x0006, 1);
-
-		info.cookie = tmptlv->value;
-	}
-
-	/*
-	 * The email address attached to this account
-	 *   Not available for ICQ logins.
-	 */
-	if (aim_gettlv(tlvlist, 0x0011, 1)) {
-		info.email = aim_gettlv_str(tlvlist, 0x0011, 1);
-	}
-
-	/*
-	 * The registration status.  (Not real sure what it means.)
-	 *   Not available for ICQ logins.
-	 *
-	 *   1 = No disclosure
-	 *   2 = Limited disclosure
-	 *   3 = Full disclosure
-	 *
-	 * This has to do with whether your email address is available
-	 * to other users or not.  AFAIK, this feature is no longer used.
-	 *
-	 */
-	if (aim_gettlv(tlvlist, 0x0013, 1)) {
-		info.regstatus = aim_gettlv16(tlvlist, 0x0013, 1);
-	}
-
-	if (aim_gettlv(tlvlist, 0x0040, 1)) {
-		info.latestbeta.build = aim_gettlv32(tlvlist, 0x0040, 1);
-	}
-	if (aim_gettlv(tlvlist, 0x0041, 1)) {
-		info.latestbeta.url = aim_gettlv_str(tlvlist, 0x0041, 1);
-	}
-	if (aim_gettlv(tlvlist, 0x0042, 1)) {
-		info.latestbeta.info = aim_gettlv_str(tlvlist, 0x0042, 1);
-	}
-	if (aim_gettlv(tlvlist, 0x0043, 1)) {
-		info.latestbeta.name = aim_gettlv_str(tlvlist, 0x0043, 1);
-	}
-	if (aim_gettlv(tlvlist, 0x0048, 1)) {
-		; /* no idea what this is */
-
-	}
-	if (aim_gettlv(tlvlist, 0x0044, 1)) {
-		info.latestrelease.build = aim_gettlv32(tlvlist, 0x0044, 1);
-	}
-	if (aim_gettlv(tlvlist, 0x0045, 1)) {
-		info.latestrelease.url = aim_gettlv_str(tlvlist, 0x0045, 1);
-	}
-	if (aim_gettlv(tlvlist, 0x0046, 1)) {
-		info.latestrelease.info = aim_gettlv_str(tlvlist, 0x0046, 1);
-	}
-	if (aim_gettlv(tlvlist, 0x0047, 1)) {
-		info.latestrelease.name = aim_gettlv_str(tlvlist, 0x0047, 1);
-	}
-	if (aim_gettlv(tlvlist, 0x0049, 1)) {
-		; /* no idea what this is */
-
-
-	}
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac ? snac->family : 0x0017, snac ? snac->subtype : 0x0003))) {
-		ret = userfunc(sess, rx, &info);
-	}
-
-	g_free(info.sn);
-	g_free(info.bosip);
-	g_free(info.errorurl);
-	g_free(info.email);
-	g_free(info.latestrelease.name);
-	g_free(info.latestrelease.url);
-	g_free(info.latestrelease.info);
-	g_free(info.latestbeta.name);
-	g_free(info.latestbeta.url);
-	g_free(info.latestbeta.info);
-
-	aim_freetlvchain(&tlvlist);
-
-	return ret;
-}
-
-/*
- * Middle handler for 0017/0007 SNACs.  Contains the auth key prefixed
- * by only its length in a two byte word.
- *
- * Calls the client, which should then use the value to call aim_send_login.
- *
- */
-static int keyparse(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int keylen, ret = 1;
-	aim_rxcallback_t userfunc;
-	char *keystr;
-
-	keylen = aimbs_get16(bs);
-	keystr = aimbs_getstr(bs, keylen);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, keystr);
-	}
-
-	g_free(keystr);
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0003) {
-		return parse(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == 0x0007) {
-		return keyparse(sess, mod, rx, snac, bs);
-	}
-
-	return 0;
-}
-
-int auth_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x0017;
-	mod->version = 0x0000;
-	mod->flags = 0;
-	strncpy(mod->name, "auth", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
-
Index: protocols/oscar/bos.c
===================================================================
--- protocols/oscar/bos.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,85 +1,0 @@
-#include <aim.h>
-#include "bos.h"
-
-/* Request BOS rights (group 9, type 2) */
-int aim_bos_reqrights(aim_session_t *sess, aim_conn_t *conn)
-{
-	return aim_genericreq_n(sess, conn, 0x0009, 0x0002);
-}
-
-/* BOS Rights (group 9, type 3) */
-static int rights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_rxcallback_t userfunc;
-	aim_tlvlist_t *tlvlist;
-	guint16 maxpermits = 0, maxdenies = 0;
-	int ret = 0;
-
-	/*
-	 * TLVs follow
-	 */
-	tlvlist = aim_readtlvchain(bs);
-
-	/*
-	 * TLV type 0x0001: Maximum number of buddies on permit list.
-	 */
-	if (aim_gettlv(tlvlist, 0x0001, 1)) {
-		maxpermits = aim_gettlv16(tlvlist, 0x0001, 1);
-	}
-
-	/*
-	 * TLV type 0x0002: Maximum number of buddies on deny list.
-	 */
-	if (aim_gettlv(tlvlist, 0x0002, 1)) {
-		maxdenies = aim_gettlv16(tlvlist, 0x0002, 1);
-	}
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, maxpermits, maxdenies);
-	}
-
-	aim_freetlvchain(&tlvlist);
-
-	return ret;
-}
-
-/*
- * Set group permisson mask (group 9, type 4)
- *
- * Normally 0x1f (all classes).
- *
- * The group permission mask allows you to keep users of a certain
- * class or classes from talking to you.  The mask should be
- * a bitwise OR of all the user classes you want to see you.
- *
- */
-int aim_bos_setgroupperm(aim_session_t *sess, aim_conn_t *conn, guint32 mask)
-{
-	return aim_genericreq_l(sess, conn, 0x0009, 0x0004, &mask);
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0003) {
-		return rights(sess, mod, rx, snac, bs);
-	}
-
-	return 0;
-}
-
-int bos_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x0009;
-	mod->version = 0x0001;
-	mod->toolid = 0x0110;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "bos", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
-
-
Index: protocols/oscar/bos.h
===================================================================
--- protocols/oscar/bos.h	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,14 +1,0 @@
-#ifndef __OSCAR_BOS_H__
-#define __OSCAR_BOS_H__
-
-#define AIM_CB_FAM_BOS 0x0009
-
-/*
- * SNAC Family: Misc BOS Services.
- */
-#define AIM_CB_BOS_ERROR 0x0001
-#define AIM_CB_BOS_RIGHTSQUERY 0x0002
-#define AIM_CB_BOS_RIGHTS 0x0003
-#define AIM_CB_BOS_DEFAULT 0xffff
-
-#endif /* __OSCAR_BOS_H__ */
Index: protocols/oscar/buddylist.c
===================================================================
--- protocols/oscar/buddylist.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,97 +1,0 @@
-#include <aim.h>
-#include "buddylist.h"
-
-/*
- * Oncoming Buddy notifications contain a subset of the
- * user information structure.  Its close enough to run
- * through aim_extractuserinfo() however.
- *
- * Although the offgoing notification contains no information,
- * it is still in a format parsable by extractuserinfo.
- *
- */
-static int buddychange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_userinfo_t userinfo;
-	aim_rxcallback_t userfunc;
-
-	aim_extractuserinfo(sess, bs, &userinfo);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		return userfunc(sess, rx, &userinfo);
-	}
-
-	return 0;
-}
-
-static int rights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_rxcallback_t userfunc;
-	aim_tlvlist_t *tlvlist;
-	guint16 maxbuddies = 0, maxwatchers = 0;
-	int ret = 0;
-
-	/*
-	 * TLVs follow
-	 */
-	tlvlist = aim_readtlvchain(bs);
-
-	/*
-	 * TLV type 0x0001: Maximum number of buddies.
-	 */
-	if (aim_gettlv(tlvlist, 0x0001, 1)) {
-		maxbuddies = aim_gettlv16(tlvlist, 0x0001, 1);
-	}
-
-	/*
-	 * TLV type 0x0002: Maximum number of watchers.
-	 *
-	 * Watchers are other users who have you on their buddy
-	 * list.  (This is called the "reverse list" by a certain
-	 * other IM protocol.)
-	 *
-	 */
-	if (aim_gettlv(tlvlist, 0x0002, 1)) {
-		maxwatchers = aim_gettlv16(tlvlist, 0x0002, 1);
-	}
-
-	/*
-	 * TLV type 0x0003: Unknown.
-	 *
-	 * ICQ only?
-	 */
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, maxbuddies, maxwatchers);
-	}
-
-	aim_freetlvchain(&tlvlist);
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0003) {
-		return rights(sess, mod, rx, snac, bs);
-	} else if ((snac->subtype == 0x000b) || (snac->subtype == 0x000c)) {
-		return buddychange(sess, mod, rx, snac, bs);
-	}
-
-	return 0;
-}
-
-int buddylist_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x0003;
-	mod->version = 0x0001;
-	mod->toolid = 0x0110;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "buddylist", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
Index: protocols/oscar/buddylist.h
===================================================================
--- protocols/oscar/buddylist.h	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,19 +1,0 @@
-#ifndef __OSCAR_BUDDYLIST_H__
-#define __OSCAR_BUDDYLIST_H__
-
-#define AIM_CB_FAM_BUD 0x0003
-
-/*
- * SNAC Family: Buddy List Management Services.
- */
-#define AIM_CB_BUD_ERROR 0x0001
-#define AIM_CB_BUD_REQRIGHTS 0x0002
-#define AIM_CB_BUD_RIGHTSINFO 0x0003
-#define AIM_CB_BUD_ADDBUDDY 0x0004
-#define AIM_CB_BUD_REMBUDDY 0x0005
-#define AIM_CB_BUD_REJECT 0x000a
-#define AIM_CB_BUD_ONCOMING 0x000b
-#define AIM_CB_BUD_OFFGOING 0x000c
-#define AIM_CB_BUD_DEFAULT 0xffff
-
-#endif /* __OSCAR_BUDDYLIST_H__ */
Index: protocols/oscar/chat.c
===================================================================
--- protocols/oscar/chat.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,671 +1,0 @@
-/*
- * aim_chat.c
- *
- * Routines for the Chat service.
- *
- */
-
-#include <aim.h>
-#include <glib.h>
-#include "info.h"
-
-/* Stored in the ->priv of chat connections */
-struct chatconnpriv {
-	guint16 exchange;
-	char *name;
-	guint16 instance;
-};
-
-void aim_conn_kill_chat(aim_session_t *sess, aim_conn_t *conn)
-{
-	struct chatconnpriv *ccp = (struct chatconnpriv *) conn->priv;
-
-	if (ccp) {
-		g_free(ccp->name);
-	}
-	g_free(ccp);
-
-	return;
-}
-
-/*
- * Send a Chat Message.
- *
- * Possible flags:
- *   AIM_CHATFLAGS_NOREFLECT   --  Unset the flag that requests messages
- *                                 should be sent to their sender.
- *   AIM_CHATFLAGS_AWAY        --  Mark the message as an autoresponse
- *                                 (Note that WinAIM does not honor this,
- *                                 and displays the message as normal.)
- *
- * XXX convert this to use tlvchains
- */
-int aim_chat_send_im(aim_session_t *sess, aim_conn_t *conn, guint16 flags, const char *msg, int msglen)
-{
-	int i;
-	aim_frame_t *fr;
-	aim_msgcookie_t *cookie;
-	aim_snacid_t snacid;
-	guint8 ckstr[8];
-	aim_tlvlist_t *otl = NULL, *itl = NULL;
-
-	if (!sess || !conn || !msg || (msglen <= 0)) {
-		return 0;
-	}
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, 0x000e, 0x0005, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x000e, 0x0005, 0x0000, snacid);
-
-
-	/*
-	 * Generate a random message cookie.
-	 *
-	 * XXX mkcookie should generate the cookie and cache it in one
-	 * operation to preserve uniqueness.
-	 *
-	 */
-	for (i = 0; i < sizeof(ckstr); i++) {
-		(void) aimutil_put8(ckstr + i, (guint8) rand());
-	}
-
-
-	cookie = aim_mkcookie(ckstr, AIM_COOKIETYPE_CHAT, NULL);
-	cookie->data = NULL; /* XXX store something useful here */
-
-	aim_cachecookie(sess, cookie);
-
-	for (i = 0; i < sizeof(ckstr); i++) {
-		aimbs_put8(&fr->data, ckstr[i]);
-	}
-
-
-	/*
-	 * Channel ID.
-	 */
-	aimbs_put16(&fr->data, 0x0003);
-
-
-	/*
-	 * Type 1: Flag meaning this message is destined to the room.
-	 */
-	aim_addtlvtochain_noval(&otl, 0x0001);
-
-	/*
-	 * Type 6: Reflect
-	 */
-	if (!(flags & AIM_CHATFLAGS_NOREFLECT)) {
-		aim_addtlvtochain_noval(&otl, 0x0006);
-	}
-
-	/*
-	 * Type 7: Autoresponse
-	 */
-	if (flags & AIM_CHATFLAGS_AWAY) {
-		aim_addtlvtochain_noval(&otl, 0x0007);
-	}
-
-	/* [WvG] This wasn't there originally, but we really should send
-	         the right charset flags, as we also do with normal
-	         messages. Hope this will work. :-) */
-	/*
-	if (flags & AIM_CHATFLAGS_UNICODE)
-	        aimbs_put16(&fr->data, 0x0002);
-	else if (flags & AIM_CHATFLAGS_ISO_8859_1)
-	        aimbs_put16(&fr->data, 0x0003);
-	else
-	        aimbs_put16(&fr->data, 0x0000);
-
-	aimbs_put16(&fr->data, 0x0000);
-	*/
-
-	/*
-	 * SubTLV: Type 1: Message
-	 */
-	aim_addtlvtochain_raw(&itl, 0x0001, strlen(msg), (guint8 *) msg);
-
-	/*
-	 * Type 5: Message block.  Contains more TLVs.
-	 *
-	 * This could include other information... We just
-	 * put in a message TLV however.
-	 *
-	 */
-	aim_addtlvtochain_frozentlvlist(&otl, 0x0005, &itl);
-
-	aim_writetlvchain(&fr->data, &otl);
-
-	aim_freetlvchain(&itl);
-	aim_freetlvchain(&otl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Join a room of name roomname.  This is the first step to joining an
- * already created room.  It's basically a Service Request for
- * family 0x000e, with a little added on to specify the exchange and room
- * name.
- */
-int aim_chat_join(aim_session_t *sess, aim_conn_t *conn, guint16 exchange, const char *roomname, guint16 instance)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
-	struct chatsnacinfo csi;
-
-	if (!sess || !conn || !roomname || !strlen(roomname)) {
-		return -EINVAL;
-	}
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 512))) {
-		return -ENOMEM;
-	}
-
-	memset(&csi, 0, sizeof(csi));
-	csi.exchange = exchange;
-	strncpy(csi.name, roomname, sizeof(csi.name));
-	csi.instance = instance;
-
-	snacid = aim_cachesnac(sess, 0x0001, 0x0004, 0x0000, &csi, sizeof(csi));
-	aim_putsnac(&fr->data, 0x0001, 0x0004, 0x0000, snacid);
-
-	/*
-	 * Requesting service chat (0x000e)
-	 */
-	aimbs_put16(&fr->data, 0x000e);
-
-	aim_addtlvtochain_chatroom(&tl, 0x0001, exchange, roomname, instance);
-	aim_writetlvchain(&fr->data, &tl);
-	aim_freetlvchain(&tl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-int aim_chat_readroominfo(aim_bstream_t *bs, struct aim_chat_roominfo *outinfo)
-{
-	int namelen;
-
-	if (!bs || !outinfo) {
-		return 0;
-	}
-
-	outinfo->exchange = aimbs_get16(bs);
-	namelen = aimbs_get8(bs);
-	outinfo->name = aimbs_getstr(bs, namelen);
-	outinfo->instance = aimbs_get16(bs);
-
-	return 0;
-}
-
-/*
- * conn must be a BOS connection!
- */
-int aim_chat_invite(aim_session_t *sess, aim_conn_t *conn, const char *sn, const char *msg, guint16 exchange,
-                    const char *roomname, guint16 instance)
-{
-	int i;
-	aim_frame_t *fr;
-	aim_msgcookie_t *cookie;
-	struct aim_invite_priv *priv;
-	guint8 ckstr[8];
-	aim_snacid_t snacid;
-	aim_tlvlist_t *otl = NULL, *itl = NULL;
-	guint8 *hdr;
-	int hdrlen;
-	aim_bstream_t hdrbs;
-
-	if (!sess || !conn || !sn || !msg || !roomname) {
-		return -EINVAL;
-	}
-
-	if (conn->type != AIM_CONN_TYPE_BOS) {
-		return -EINVAL;
-	}
-
-	if (!(fr =
-	              aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152 + strlen(sn) + strlen(roomname) +
-	                         strlen(msg)))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, sn, strlen(sn) + 1);
-	aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
-
-
-	/*
-	 * Cookie
-	 */
-	for (i = 0; i < sizeof(ckstr); i++) {
-		(void) aimutil_put8(ckstr, (guint8) rand());
-	}
-
-	/* XXX should be uncached by an unwritten 'invite accept' handler */
-	if ((priv = g_malloc(sizeof(struct aim_invite_priv)))) {
-		priv->sn = g_strdup(sn);
-		priv->roomname = g_strdup(roomname);
-		priv->exchange = exchange;
-		priv->instance = instance;
-	}
-
-	if ((cookie = aim_mkcookie(ckstr, AIM_COOKIETYPE_INVITE, priv))) {
-		aim_cachecookie(sess, cookie);
-	} else {
-		g_free(priv);
-	}
-
-	for (i = 0; i < sizeof(ckstr); i++) {
-		aimbs_put8(&fr->data, ckstr[i]);
-	}
-
-
-	/*
-	 * Channel (2)
-	 */
-	aimbs_put16(&fr->data, 0x0002);
-
-	/*
-	 * Dest sn
-	 */
-	aimbs_put8(&fr->data, strlen(sn));
-	aimbs_putraw(&fr->data, (guint8 *) sn, strlen(sn));
-
-	/*
-	 * TLV t(0005)
-	 *
-	 * Everything else is inside this TLV.
-	 *
-	 * Sigh.  AOL was rather inconsistent right here.  So we have
-	 * to play some minor tricks.  Right inside the type 5 is some
-	 * raw data, followed by a series of TLVs.
-	 *
-	 */
-	hdrlen = 2 + 8 + 16 + 6 + 4 + 4 + strlen(msg) + 4 + 2 + 1 + strlen(roomname) + 2;
-	hdr = g_malloc(hdrlen);
-	aim_bstream_init(&hdrbs, hdr, hdrlen);
-
-	aimbs_put16(&hdrbs, 0x0000); /* Unknown! */
-	aimbs_putraw(&hdrbs, ckstr, sizeof(ckstr)); /* I think... */
-	aim_putcap(&hdrbs, AIM_CAPS_CHAT);
-
-	aim_addtlvtochain16(&itl, 0x000a, 0x0001);
-	aim_addtlvtochain_noval(&itl, 0x000f);
-	aim_addtlvtochain_raw(&itl, 0x000c, strlen(msg), (guint8 *) msg);
-	aim_addtlvtochain_chatroom(&itl, 0x2711, exchange, roomname, instance);
-	aim_writetlvchain(&hdrbs, &itl);
-
-	aim_addtlvtochain_raw(&otl, 0x0005, aim_bstream_curpos(&hdrbs), hdr);
-
-	aim_writetlvchain(&fr->data, &otl);
-
-	g_free(hdr);
-	aim_freetlvchain(&itl);
-	aim_freetlvchain(&otl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * General room information.  Lots of stuff.
- *
- * Values I know are in here but I havent attached
- * them to any of the 'Unknown's:
- *	- Language (English)
- *
- * SNAC 000e/0002
- */
-static int infoupdate(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_userinfo_t *userinfo = NULL;
-	aim_rxcallback_t userfunc;
-	int ret = 0;
-	int usercount = 0;
-	guint8 detaillevel = 0;
-	char *roomname = NULL;
-	struct aim_chat_roominfo roominfo;
-	aim_tlvlist_t *tlvlist;
-	char *roomdesc = NULL;
-	guint16 flags = 0;
-	guint32 creationtime = 0;
-	guint16 maxmsglen = 0, maxvisiblemsglen = 0;
-	guint16 unknown_d2 = 0, unknown_d5 = 0;
-
-	aim_chat_readroominfo(bs, &roominfo);
-
-	detaillevel = aimbs_get8(bs);
-
-	if (detaillevel != 0x02) {
-		imcb_error(sess->aux_data, "Only detaillevel 0x2 is support at the moment");
-		return 1;
-	}
-
-	aimbs_get16(bs); /* tlv count */
-
-	/*
-	 * Everything else are TLVs.
-	 */
-	tlvlist = aim_readtlvchain(bs);
-
-	/*
-	 * TLV type 0x006a is the room name in Human Readable Form.
-	 */
-	if (aim_gettlv(tlvlist, 0x006a, 1)) {
-		roomname = aim_gettlv_str(tlvlist, 0x006a, 1);
-	}
-
-	/*
-	 * Type 0x006f: Number of occupants.
-	 */
-	if (aim_gettlv(tlvlist, 0x006f, 1)) {
-		usercount = aim_gettlv16(tlvlist, 0x006f, 1);
-	}
-
-	/*
-	 * Type 0x0073:  Occupant list.
-	 */
-	if (aim_gettlv(tlvlist, 0x0073, 1)) {
-		int curoccupant = 0;
-		aim_tlv_t *tmptlv;
-		aim_bstream_t occbs;
-
-		tmptlv = aim_gettlv(tlvlist, 0x0073, 1);
-
-		/* Allocate enough userinfo structs for all occupants */
-		userinfo = g_new0(aim_userinfo_t, usercount);
-
-		aim_bstream_init(&occbs, tmptlv->value, tmptlv->length);
-
-		while (curoccupant < usercount) {
-			aim_extractuserinfo(sess, &occbs, &userinfo[curoccupant++]);
-		}
-	}
-
-	/*
-	 * Type 0x00c9: Flags. (AIM_CHATROOM_FLAG)
-	 */
-	if (aim_gettlv(tlvlist, 0x00c9, 1)) {
-		flags = aim_gettlv16(tlvlist, 0x00c9, 1);
-	}
-
-	/*
-	 * Type 0x00ca: Creation time (4 bytes)
-	 */
-	if (aim_gettlv(tlvlist, 0x00ca, 1)) {
-		creationtime = aim_gettlv32(tlvlist, 0x00ca, 1);
-	}
-
-	/*
-	 * Type 0x00d1: Maximum Message Length
-	 */
-	if (aim_gettlv(tlvlist, 0x00d1, 1)) {
-		maxmsglen = aim_gettlv16(tlvlist, 0x00d1, 1);
-	}
-
-	/*
-	 * Type 0x00d2: Unknown. (2 bytes)
-	 */
-	if (aim_gettlv(tlvlist, 0x00d2, 1)) {
-		unknown_d2 = aim_gettlv16(tlvlist, 0x00d2, 1);
-	}
-
-	/*
-	 * Type 0x00d3: Room Description
-	 */
-	if (aim_gettlv(tlvlist, 0x00d3, 1)) {
-		roomdesc = aim_gettlv_str(tlvlist, 0x00d3, 1);
-	}
-
-	/*
-	 * Type 0x000d4: Unknown (flag only)
-	 */
-	if (aim_gettlv(tlvlist, 0x000d4, 1)) {
-		;
-	}
-
-	/*
-	 * Type 0x00d5: Unknown. (1 byte)
-	 */
-	if (aim_gettlv(tlvlist, 0x00d5, 1)) {
-		unknown_d5 = aim_gettlv8(tlvlist, 0x00d5, 1);
-	}
-
-
-	/*
-	 * Type 0x00d6: Encoding 1 ("us-ascii")
-	 */
-	if (aim_gettlv(tlvlist, 0x000d6, 1)) {
-		;
-	}
-
-	/*
-	 * Type 0x00d7: Language 1 ("en")
-	 */
-	if (aim_gettlv(tlvlist, 0x000d7, 1)) {
-		;
-	}
-
-	/*
-	 * Type 0x00d8: Encoding 2 ("us-ascii")
-	 */
-	if (aim_gettlv(tlvlist, 0x000d8, 1)) {
-		;
-	}
-
-	/*
-	 * Type 0x00d9: Language 2 ("en")
-	 */
-	if (aim_gettlv(tlvlist, 0x000d9, 1)) {
-		;
-	}
-
-	/*
-	 * Type 0x00da: Maximum visible message length
-	 */
-	if (aim_gettlv(tlvlist, 0x000da, 1)) {
-		maxvisiblemsglen = aim_gettlv16(tlvlist, 0x00da, 1);
-	}
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess,
-		               rx,
-		               &roominfo,
-		               roomname,
-		               usercount,
-		               userinfo,
-		               roomdesc,
-		               flags,
-		               creationtime,
-		               maxmsglen,
-		               unknown_d2,
-		               unknown_d5,
-		               maxvisiblemsglen);
-	}
-
-	g_free(roominfo.name);
-	g_free(userinfo);
-	g_free(roomname);
-	g_free(roomdesc);
-	aim_freetlvchain(&tlvlist);
-
-	return ret;
-}
-
-static int userlistchange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac,
-                          aim_bstream_t *bs)
-{
-	aim_userinfo_t *userinfo = NULL;
-	aim_rxcallback_t userfunc;
-	int curcount = 0, ret = 0;
-
-	while (aim_bstream_empty(bs)) {
-		curcount++;
-		userinfo = g_realloc(userinfo, curcount * sizeof(aim_userinfo_t));
-		aim_extractuserinfo(sess, bs, &userinfo[curcount - 1]);
-	}
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, curcount, userinfo);
-	}
-
-	g_free(userinfo);
-
-	return ret;
-}
-
-/*
- * We could probably include this in the normal ICBM parsing
- * code as channel 0x0003, however, since only the start
- * would be the same, we might as well do it here.
- *
- * General outline of this SNAC:
- *   snac
- *   cookie
- *   channel id
- *   tlvlist
- *     unknown
- *     source user info
- *       name
- *       evility
- *       userinfo tlvs
- *         online time
- *         etc
- *     message metatlv
- *       message tlv
- *         message string
- *       possibly others
- *
- */
-static int incomingmsg(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_userinfo_t userinfo;
-	aim_rxcallback_t userfunc;
-	int ret = 0;
-	guint8 *cookie;
-	guint16 channel;
-	aim_tlvlist_t *otl;
-	char *msg = NULL;
-	aim_msgcookie_t *ck;
-
-	memset(&userinfo, 0, sizeof(aim_userinfo_t));
-
-	/*
-	 * ICBM Cookie.  Uncache it.
-	 */
-	cookie = aimbs_getraw(bs, 8);
-
-	if ((ck = aim_uncachecookie(sess, cookie, AIM_COOKIETYPE_CHAT))) {
-		g_free(ck->data);
-		g_free(ck);
-	}
-
-	/*
-	 * Channel ID
-	 *
-	 * Channels 1 and 2 are implemented in the normal ICBM
-	 * parser.
-	 *
-	 * We only do channel 3 here.
-	 *
-	 */
-	channel = aimbs_get16(bs);
-
-	if (channel != 0x0003) {
-		imcb_error(sess->aux_data, "unknown channel!");
-		return 0;
-	}
-
-	/*
-	 * Start parsing TLVs right away.
-	 */
-	otl = aim_readtlvchain(bs);
-
-	/*
-	 * Type 0x0003: Source User Information
-	 */
-	if (aim_gettlv(otl, 0x0003, 1)) {
-		aim_tlv_t *userinfotlv;
-		aim_bstream_t tbs;
-
-		userinfotlv = aim_gettlv(otl, 0x0003, 1);
-
-		aim_bstream_init(&tbs, userinfotlv->value, userinfotlv->length);
-		aim_extractuserinfo(sess, &tbs, &userinfo);
-	}
-
-	/*
-	 * Type 0x0001: If present, it means it was a message to the
-	 * room (as opposed to a whisper).
-	 */
-	if (aim_gettlv(otl, 0x0001, 1)) {
-		;
-	}
-
-	/*
-	 * Type 0x0005: Message Block.  Conains more TLVs.
-	 */
-	if (aim_gettlv(otl, 0x0005, 1)) {
-		aim_tlvlist_t *itl;
-		aim_tlv_t *msgblock;
-		aim_bstream_t tbs;
-
-		msgblock = aim_gettlv(otl, 0x0005, 1);
-		aim_bstream_init(&tbs, msgblock->value, msgblock->length);
-		itl = aim_readtlvchain(&tbs);
-
-		/*
-		 * Type 0x0001: Message.
-		 */
-		if (aim_gettlv(itl, 0x0001, 1)) {
-			msg = aim_gettlv_str(itl, 0x0001, 1);
-		}
-
-		aim_freetlvchain(&itl);
-	}
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, &userinfo, msg);
-	}
-
-	g_free(cookie);
-	g_free(msg);
-	aim_freetlvchain(&otl);
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0002) {
-		return infoupdate(sess, mod, rx, snac, bs);
-	} else if ((snac->subtype == 0x0003) || (snac->subtype == 0x0004)) {
-		return userlistchange(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == 0x0006) {
-		return incomingmsg(sess, mod, rx, snac, bs);
-	}
-
-	return 0;
-}
-
-int chat_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x000e;
-	mod->version = 0x0001;
-	mod->toolid = 0x0010;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "chat", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
Index: protocols/oscar/chat.h
===================================================================
--- protocols/oscar/chat.h	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,17 +1,0 @@
-#ifndef __OSCAR_CHAT_H__
-#define __OSCAR_CHAT_H__
-
-#define AIM_CB_FAM_CHT 0x000e /* Chat */
-
-/*
- * SNAC Family: Chat Services
- */
-#define AIM_CB_CHT_ERROR 0x0001
-#define AIM_CB_CHT_ROOMINFOUPDATE 0x0002
-#define AIM_CB_CHT_USERJOIN 0x0003
-#define AIM_CB_CHT_USERLEAVE 0x0004
-#define AIM_CB_CHT_OUTGOINGMSG 0x0005
-#define AIM_CB_CHT_INCOMINGMSG 0x0006
-#define AIM_CB_CHT_DEFAULT 0xffff
-
-#endif /* __OSCAR_CHAT_H__ */
Index: protocols/oscar/chatnav.c
===================================================================
--- protocols/oscar/chatnav.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,452 +1,0 @@
-/*
- * Handle ChatNav.
- *
- * [The ChatNav(igation) service does various things to keep chat
- *  alive.  It provides room information, room searching and creating,
- *  as well as giving users the right ("permission") to use chat.]
- *
- */
-
-#include <aim.h>
-#include "chatnav.h"
-
-/*
- * conn must be a chatnav connection!
- */
-int aim_chatnav_reqrights(aim_session_t *sess, aim_conn_t *conn)
-{
-	return aim_genericreq_n_snacid(sess, conn, 0x000d, 0x0002);
-}
-
-int aim_chatnav_createroom(aim_session_t *sess, aim_conn_t *conn, const char *name, guint16 exchange)
-{
-	static const char ck[] = { "create" };
-	static const char lang[] = { "en" };
-	static const char charset[] = { "us-ascii" };
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, 0x000d, 0x0008, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x000d, 0x0008, 0x0000, snacid);
-
-	/* exchange */
-	aimbs_put16(&fr->data, exchange);
-
-	/*
-	 * This looks to be a big hack.  You'll note that this entire
-	 * SNAC is just a room info structure, but the hard room name,
-	 * here, is set to "create".
-	 *
-	 * Either this goes on the "list of questions concerning
-	 * why-the-hell-did-you-do-that", or this value is completly
-	 * ignored.  Without experimental evidence, but a good knowledge of
-	 * AOL style, I'm going to guess that it is the latter, and that
-	 * the value of the room name in create requests is ignored.
-	 */
-	aimbs_put8(&fr->data, strlen(ck));
-	aimbs_putraw(&fr->data, (guint8 *) ck, strlen(ck));
-
-	/*
-	 * instance
-	 *
-	 * Setting this to 0xffff apparently assigns the last instance.
-	 *
-	 */
-	aimbs_put16(&fr->data, 0xffff);
-
-	/* detail level */
-	aimbs_put8(&fr->data, 0x01);
-
-	aim_addtlvtochain_raw(&tl, 0x00d3, strlen(name), (guint8 *) name);
-	aim_addtlvtochain_raw(&tl, 0x00d6, strlen(charset), (guint8 *) charset);
-	aim_addtlvtochain_raw(&tl, 0x00d7, strlen(lang), (guint8 *) lang);
-
-	/* tlvcount */
-	aimbs_put16(&fr->data, aim_counttlvchain(&tl));
-	aim_writetlvchain(&fr->data, &tl);
-
-	aim_freetlvchain(&tl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-static int parseinfo_perms(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac,
-                           aim_bstream_t *bs, aim_snac_t *snac2)
-{
-	aim_rxcallback_t userfunc;
-	int ret = 0;
-	struct aim_chat_exchangeinfo *exchanges = NULL;
-	int curexchange;
-	aim_tlv_t *exchangetlv;
-	guint8 maxrooms = 0;
-	aim_tlvlist_t *tlvlist, *innerlist;
-
-	tlvlist = aim_readtlvchain(bs);
-
-	/*
-	 * Type 0x0002: Maximum concurrent rooms.
-	 */
-	if (aim_gettlv(tlvlist, 0x0002, 1)) {
-		maxrooms = aim_gettlv8(tlvlist, 0x0002, 1);
-	}
-
-	/*
-	 * Type 0x0003: Exchange information
-	 *
-	 * There can be any number of these, each one
-	 * representing another exchange.
-	 *
-	 */
-	for (curexchange = 0; ((exchangetlv = aim_gettlv(tlvlist, 0x0003, curexchange + 1))); ) {
-		aim_bstream_t tbs;
-
-		aim_bstream_init(&tbs, exchangetlv->value, exchangetlv->length);
-
-		curexchange++;
-
-		exchanges = g_realloc(exchanges, curexchange * sizeof(struct aim_chat_exchangeinfo));
-
-		/* exchange number */
-		exchanges[curexchange - 1].number = aimbs_get16(&tbs);
-		innerlist = aim_readtlvchain(&tbs);
-
-		/*
-		 * Type 0x000a: Unknown.
-		 *
-		 * Usually three bytes: 0x0114 (exchange 1) or 0x010f (others).
-		 *
-		 */
-		if (aim_gettlv(innerlist, 0x000a, 1)) {
-			;
-		}
-
-		/*
-		 * Type 0x000d: Unknown.
-		 */
-		if (aim_gettlv(innerlist, 0x000d, 1)) {
-			;
-		}
-
-		/*
-		 * Type 0x0004: Unknown
-		 */
-		if (aim_gettlv(innerlist, 0x0004, 1)) {
-			;
-		}
-
-		/*
-		 * Type 0x0002: Unknown
-		 */
-		if (aim_gettlv(innerlist, 0x0002, 1)) {
-			;
-		}
-
-		/*
-		 * Type 0x00c9: Flags
-		 *
-		 * 1 Evilable
-		 * 2 Nav Only
-		 * 4 Instancing Allowed
-		 * 8 Occupant Peek Allowed
-		 *
-		 */
-		if (aim_gettlv(innerlist, 0x00c9, 1)) {
-			exchanges[curexchange - 1].flags = aim_gettlv16(innerlist, 0x00c9, 1);
-		}
-
-		/*
-		 * Type 0x00ca: Creation Date
-		 */
-		if (aim_gettlv(innerlist, 0x00ca, 1)) {
-			;
-		}
-
-		/*
-		 * Type 0x00d0: Mandatory Channels?
-		 */
-		if (aim_gettlv(innerlist, 0x00d0, 1)) {
-			;
-		}
-
-		/*
-		 * Type 0x00d1: Maximum Message length
-		 */
-		if (aim_gettlv(innerlist, 0x00d1, 1)) {
-			;
-		}
-
-		/*
-		 * Type 0x00d2: Maximum Occupancy?
-		 */
-		if (aim_gettlv(innerlist, 0x00d2, 1)) {
-			;
-		}
-
-		/*
-		 * Type 0x00d3: Exchange Description
-		 */
-		if (aim_gettlv(innerlist, 0x00d3, 1)) {
-			exchanges[curexchange - 1].name = aim_gettlv_str(innerlist, 0x00d3, 1);
-		} else {
-			exchanges[curexchange - 1].name = NULL;
-		}
-
-		/*
-		 * Type 0x00d4: Exchange Description URL
-		 */
-		if (aim_gettlv(innerlist, 0x00d4, 1)) {
-			;
-		}
-
-		/*
-		 * Type 0x00d5: Creation Permissions
-		 *
-		 * 0  Creation not allowed
-		 * 1  Room creation allowed
-		 * 2  Exchange creation allowed
-		 *
-		 */
-		if (aim_gettlv(innerlist, 0x00d5, 1)) {
-			aim_gettlv8(innerlist, 0x00d5, 1); /* createperms */
-		}
-
-		/*
-		 * Type 0x00d6: Character Set (First Time)
-		 */
-		if (aim_gettlv(innerlist, 0x00d6, 1)) {
-			exchanges[curexchange - 1].charset1 = aim_gettlv_str(innerlist, 0x00d6, 1);
-		} else {
-			exchanges[curexchange - 1].charset1 = NULL;
-		}
-
-		/*
-		 * Type 0x00d7: Language (First Time)
-		 */
-		if (aim_gettlv(innerlist, 0x00d7, 1)) {
-			exchanges[curexchange - 1].lang1 = aim_gettlv_str(innerlist, 0x00d7, 1);
-		} else {
-			exchanges[curexchange - 1].lang1 = NULL;
-		}
-
-		/*
-		 * Type 0x00d8: Character Set (Second Time)
-		 */
-		if (aim_gettlv(innerlist, 0x00d8, 1)) {
-			exchanges[curexchange - 1].charset2 = aim_gettlv_str(innerlist, 0x00d8, 1);
-		} else {
-			exchanges[curexchange - 1].charset2 = NULL;
-		}
-
-		/*
-		 * Type 0x00d9: Language (Second Time)
-		 */
-		if (aim_gettlv(innerlist, 0x00d9, 1)) {
-			exchanges[curexchange - 1].lang2 = aim_gettlv_str(innerlist, 0x00d9, 1);
-		} else {
-			exchanges[curexchange - 1].lang2 = NULL;
-		}
-
-		/*
-		 * Type 0x00da: Unknown
-		 */
-		if (aim_gettlv(innerlist, 0x00da, 1)) {
-			;
-		}
-
-		aim_freetlvchain(&innerlist);
-	}
-
-	/*
-	 * Call client.
-	 */
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, snac2->type, maxrooms, curexchange, exchanges);
-	}
-
-	for (curexchange--; curexchange >= 0; curexchange--) {
-		g_free(exchanges[curexchange].name);
-		g_free(exchanges[curexchange].charset1);
-		g_free(exchanges[curexchange].lang1);
-		g_free(exchanges[curexchange].charset2);
-		g_free(exchanges[curexchange].lang2);
-	}
-	g_free(exchanges);
-	aim_freetlvchain(&tlvlist);
-
-	return ret;
-}
-
-static int parseinfo_create(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac,
-                            aim_bstream_t *bs, aim_snac_t *snac2)
-{
-	aim_rxcallback_t userfunc;
-	aim_tlvlist_t *tlvlist, *innerlist;
-	char *ck = NULL, *fqcn = NULL, *name = NULL;
-	guint16 exchange = 0, instance = 0, unknown = 0, flags = 0, maxmsglen = 0, maxoccupancy = 0;
-	guint32 createtime = 0;
-	guint8 createperms = 0, detaillevel;
-	int cklen;
-	aim_tlv_t *bigblock;
-	int ret = 0;
-	aim_bstream_t bbbs;
-
-	tlvlist = aim_readtlvchain(bs);
-
-	if (!(bigblock = aim_gettlv(tlvlist, 0x0004, 1))) {
-		imcb_error(sess->aux_data, "no bigblock in top tlv in create room response");
-
-		aim_freetlvchain(&tlvlist);
-		return 0;
-	}
-
-	aim_bstream_init(&bbbs, bigblock->value, bigblock->length);
-
-	exchange = aimbs_get16(&bbbs);
-	cklen = aimbs_get8(&bbbs);
-	ck = aimbs_getstr(&bbbs, cklen);
-	instance = aimbs_get16(&bbbs);
-	detaillevel = aimbs_get8(&bbbs);
-
-	if (detaillevel != 0x02) {
-		imcb_error(sess->aux_data, "unknown detaillevel in create room response");
-		aim_freetlvchain(&tlvlist);
-		g_free(ck);
-		return 0;
-	}
-
-	unknown = aimbs_get16(&bbbs);
-
-	innerlist = aim_readtlvchain(&bbbs);
-
-	if (aim_gettlv(innerlist, 0x006a, 1)) {
-		fqcn = aim_gettlv_str(innerlist, 0x006a, 1);
-	}
-
-	if (aim_gettlv(innerlist, 0x00c9, 1)) {
-		flags = aim_gettlv16(innerlist, 0x00c9, 1);
-	}
-
-	if (aim_gettlv(innerlist, 0x00ca, 1)) {
-		createtime = aim_gettlv32(innerlist, 0x00ca, 1);
-	}
-
-	if (aim_gettlv(innerlist, 0x00d1, 1)) {
-		maxmsglen = aim_gettlv16(innerlist, 0x00d1, 1);
-	}
-
-	if (aim_gettlv(innerlist, 0x00d2, 1)) {
-		maxoccupancy = aim_gettlv16(innerlist, 0x00d2, 1);
-	}
-
-	if (aim_gettlv(innerlist, 0x00d3, 1)) {
-		name = aim_gettlv_str(innerlist, 0x00d3, 1);
-	}
-
-	if (aim_gettlv(innerlist, 0x00d5, 1)) {
-		createperms = aim_gettlv8(innerlist, 0x00d5, 1);
-	}
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, snac2->type, fqcn, instance, exchange, flags, createtime, maxmsglen,
-		               maxoccupancy, createperms, unknown, name, ck);
-	}
-
-	g_free(ck);
-	g_free(name);
-	g_free(fqcn);
-	aim_freetlvchain(&innerlist);
-	aim_freetlvchain(&tlvlist);
-
-	return ret;
-}
-
-/*
- * Since multiple things can trigger this callback, we must lookup the
- * snacid to determine the original snac subtype that was called.
- *
- * XXX This isn't really how this works.  But this is:  Every d/9 response
- * has a 16bit value at the beginning. That matches to:
- *    Short Desc = 1
- *    Full Desc = 2
- *    Instance Info = 4
- *    Nav Short Desc = 8
- *    Nav Instance Info = 16
- * And then everything is really asynchronous.  There is no specific
- * attachment of a response to a create room request, for example.  Creating
- * the room yields no different a response than requesting the room's info.
- *
- */
-static int parseinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_snac_t *snac2;
-	int ret = 0;
-
-	if (!(snac2 = aim_remsnac(sess, snac->id))) {
-		imcb_error(sess->aux_data, "received response to unknown request!");
-		return 0;
-	}
-
-	if (snac2->family != 0x000d) {
-		imcb_error(sess->aux_data, "received response that maps to corrupt request!");
-		return 0;
-	}
-
-	/*
-	 * We now know what the original SNAC subtype was.
-	 */
-	if (snac2->type == 0x0002) { /* request chat rights */
-		ret = parseinfo_perms(sess, mod, rx, snac, bs, snac2);
-	} else if (snac2->type == 0x0003) {
-	}                                  /* request exchange info */
-	else if (snac2->type == 0x0004) {
-	}                                  /* request room info */
-	else if (snac2->type == 0x0005) {
-	}                                  /* request more room info */
-	else if (snac2->type == 0x0006) {
-	}                                  /* request occupant list */
-	else if (snac2->type == 0x0007) {
-	}                                  /* search for a room */
-	else if (snac2->type == 0x0008) { /* create room */
-		ret = parseinfo_create(sess, mod, rx, snac, bs, snac2);
-	} else {
-		imcb_error(sess->aux_data, "unknown request subtype");
-	}
-
-	if (snac2) {
-		g_free(snac2->data);
-	}
-	g_free(snac2);
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0009) {
-		return parseinfo(sess, mod, rx, snac, bs);
-	}
-
-	return 0;
-}
-
-int chatnav_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x000d;
-	mod->version = 0x0003;
-	mod->toolid = 0x0010;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "chatnav", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
Index: protocols/oscar/chatnav.h
===================================================================
--- protocols/oscar/chatnav.h	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,14 +1,0 @@
-#ifndef __OSCAR_CHATNAV_H__
-#define __OSCAR_CHATNAV_H__
-
-#define AIM_CB_FAM_CTN 0x000d /* ChatNav */
-
-/*
- * SNAC Family: Chat Navigation Services
- */
-#define AIM_CB_CTN_ERROR 0x0001
-#define AIM_CB_CTN_CREATE 0x0008
-#define AIM_CB_CTN_INFO 0x0009
-#define AIM_CB_CTN_DEFAULT 0xffff
-
-#endif /* __OSCAR_CHATNAV_H__ */
Index: protocols/oscar/conn.c
===================================================================
--- protocols/oscar/conn.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,633 +1,0 @@
-
-/*
- * conn.c
- *
- * Does all this gloriously nifty connection handling stuff...
- *
- */
-
-#include <aim.h>
-#include "sock.h"
-
-static int aim_logoff(aim_session_t *sess);
-
-/*
- * In OSCAR, every connection has a set of SNAC groups associated
- * with it.  These are the groups that you can send over this connection
- * without being guaranteed a "Not supported" SNAC error.
- *
- * The grand theory of things says that these associations transcend
- * what libfaim calls "connection types" (conn->type).  You can probably
- * see the elegance here, but since I want to revel in it for a bit, you
- * get to hear it all spelled out.
- *
- * So let us say that you have your core BOS connection running.  One
- * of your modules has just given you a SNAC of the group 0x0004 to send
- * you.  Maybe an IM destined for some twit in Greenland.  So you start
- * at the top of your connection list, looking for a connection that
- * claims to support group 0x0004.  You find one.  Why, that neat BOS
- * connection of yours can do that.  So you send it on its way.
- *
- * Now, say, that fellow from Greenland has friends and they all want to
- * meet up with you in a lame chat room.  This has landed you a SNAC
- * in the family 0x000e and you have to admit you're a bit lost.  You've
- * searched your connection list for someone who wants to make your life
- * easy and deliver this SNAC for you, but there isn't one there.
- *
- * Here comes the good bit.  Without even letting anyone know, particularly
- * the module that decided to send this SNAC, and definitely not that twit
- * in Greenland, you send out a service request.  In this request, you have
- * marked the need for a connection supporting group 0x000e.  A few seconds
- * later, you receive a service redirect with an IP address and a cookie in
- * it.  Great, you say.  Now I have something to do.  Off you go, making
- * that connection.  One of the first things you get from this new server
- * is a message saying that indeed it does support the group you were looking
- * for.  So you continue and send rate confirmation and all that.
- *
- * Then you remember you had that SNAC to send, and now you have a means to
- * do it, and you do, and everyone is happy.  Except the Greenlander, who is
- * still stuck in the bitter cold.
- *
- * Oh, and this is useful for building the Migration SNACs, too.  In the
- * future, this may help convince me to implement rate limit mitigation
- * for real.  We'll see.
- *
- * Just to make me look better, I'll say that I've known about this great
- * scheme for quite some time now.  But I still haven't convinced myself
- * to make libfaim work that way.  It would take a fair amount of effort,
- * and probably some client API changes as well.  (Whenever I don't want
- * to do something, I just say it would change the client API.  Then I
- * instantly have a couple of supporters of not doing it.)
- *
- * Generally, addgroup is only called by the internal handling of the
- * server ready SNAC.  So if you want to do something before that, you'll
- * have to be more creative.  That is done rather early, though, so I don't
- * think you have to worry about it.  Unless you're me.  I care deeply
- * about such inane things.
- *
- */
-void aim_conn_addgroup(aim_conn_t *conn, guint16 group)
-{
-	aim_conn_inside_t *ins = (aim_conn_inside_t *) conn->inside;
-	struct snacgroup *sg;
-
-	if (!(sg = g_malloc(sizeof(struct snacgroup)))) {
-		return;
-	}
-
-	sg->group = group;
-
-	sg->next = ins->groups;
-	ins->groups = sg;
-
-	return;
-}
-
-aim_conn_t *aim_conn_findbygroup(aim_session_t *sess, guint16 group)
-{
-	aim_conn_t *cur;
-
-	for (cur = sess->connlist; cur; cur = cur->next) {
-		aim_conn_inside_t *ins = (aim_conn_inside_t *) cur->inside;
-		struct snacgroup *sg;
-
-		for (sg = ins->groups; sg; sg = sg->next) {
-			if (sg->group == group) {
-				return cur;
-			}
-		}
-	}
-
-	return NULL;
-}
-
-static void connkill_snacgroups(struct snacgroup **head)
-{
-	struct snacgroup *sg;
-
-	for (sg = *head; sg; ) {
-		struct snacgroup *tmp;
-
-		tmp = sg->next;
-		g_free(sg);
-		sg = tmp;
-	}
-
-	*head = NULL;
-
-	return;
-}
-
-static void connkill_rates(struct rateclass **head)
-{
-	struct rateclass *rc;
-
-	for (rc = *head; rc; ) {
-		struct rateclass *tmp;
-		struct snacpair *sp;
-
-		tmp = rc->next;
-
-		for (sp = rc->members; sp; ) {
-			struct snacpair *tmpsp;
-
-			tmpsp = sp->next;
-			g_free(sp);
-			sp = tmpsp;
-		}
-		g_free(rc);
-
-		rc = tmp;
-	}
-
-	*head = NULL;
-
-	return;
-}
-
-static void connkill_real(aim_session_t *sess, aim_conn_t **deadconn)
-{
-
-	aim_rxqueue_cleanbyconn(sess, *deadconn);
-	aim_tx_cleanqueue(sess, *deadconn);
-
-	if ((*deadconn)->fd != -1) {
-		aim_conn_close(*deadconn);
-	}
-
-	/*
-	 * XXX ->priv should never be touched by the library. I know
-	 * it used to be, but I'm getting rid of all that.  Use
-	 * ->internal instead.
-	 */
-	if ((*deadconn)->priv) {
-		g_free((*deadconn)->priv);
-	}
-
-	/*
-	 * This will free ->internal if it necessary...
-	 */
-	if ((*deadconn)->type == AIM_CONN_TYPE_CHAT) {
-		aim_conn_kill_chat(sess, *deadconn);
-	}
-
-	if ((*deadconn)->inside) {
-		aim_conn_inside_t *inside = (aim_conn_inside_t *) (*deadconn)->inside;
-
-		connkill_snacgroups(&inside->groups);
-		connkill_rates(&inside->rates);
-
-		g_free(inside);
-	}
-
-	g_free(*deadconn);
-	*deadconn = NULL;
-
-	return;
-}
-
-/**
- * aim_connrst - Clears out connection list, killing remaining connections.
- * @sess: Session to be cleared
- *
- * Clears out the connection list and kills any connections left.
- *
- */
-static void aim_connrst(aim_session_t *sess)
-{
-
-	if (sess->connlist) {
-		aim_conn_t *cur = sess->connlist, *tmp;
-
-		while (cur) {
-			tmp = cur->next;
-			aim_conn_close(cur);
-			connkill_real(sess, &cur);
-			cur = tmp;
-		}
-	}
-
-	sess->connlist = NULL;
-
-	return;
-}
-
-/**
- * aim_conn_init - Reset a connection to default values.
- * @deadconn: Connection to be reset
- *
- * Initializes and/or resets a connection structure.
- *
- */
-static void aim_conn_init(aim_conn_t *deadconn)
-{
-
-	if (!deadconn) {
-		return;
-	}
-
-	deadconn->fd = -1;
-	deadconn->subtype = -1;
-	deadconn->type = -1;
-	deadconn->seqnum = 0;
-	deadconn->lastactivity = 0;
-	deadconn->forcedlatency = 0;
-	deadconn->handlerlist = NULL;
-	deadconn->priv = NULL;
-	memset(deadconn->inside, 0, sizeof(aim_conn_inside_t));
-
-	return;
-}
-
-/**
- * aim_conn_getnext - Gets a new connection structure.
- * @sess: Session
- *
- * Allocate a new empty connection structure.
- *
- */
-static aim_conn_t *aim_conn_getnext(aim_session_t *sess)
-{
-	aim_conn_t *newconn;
-
-	if (!(newconn = g_new0(aim_conn_t, 1))) {
-		return NULL;
-	}
-
-	if (!(newconn->inside = g_new0(aim_conn_inside_t, 1))) {
-		g_free(newconn);
-		return NULL;
-	}
-
-	aim_conn_init(newconn);
-
-	newconn->next = sess->connlist;
-	sess->connlist = newconn;
-
-	return newconn;
-}
-
-/**
- * aim_conn_kill - Close and free a connection.
- * @sess: Session for the connection
- * @deadconn: Connection to be freed
- *
- * Close, clear, and free a connection structure. Should never be
- * called from within libfaim.
- *
- */
-void aim_conn_kill(aim_session_t *sess, aim_conn_t **deadconn)
-{
-	aim_conn_t *cur, **prev;
-
-	if (!deadconn || !*deadconn) {
-		return;
-	}
-
-	for (prev = &sess->connlist; (cur = *prev); ) {
-		if (cur == *deadconn) {
-			*prev = cur->next;
-			break;
-		}
-		prev = &cur->next;
-	}
-
-	if (!cur) {
-		return; /* oops */
-
-	}
-	connkill_real(sess, &cur);
-
-	return;
-}
-
-/**
- * aim_conn_close - Close a connection
- * @deadconn: Connection to close
- *
- * Close (but not free) a connection.
- *
- * This leaves everything untouched except for clearing the
- * handler list and setting the fd to -1 (used to recognize
- * dead connections).  It will also remove cookies if necessary.
- *
- */
-void aim_conn_close(aim_conn_t *deadconn)
-{
-
-	if (deadconn->fd >= 3) {
-		proxy_disconnect(deadconn->fd);
-	}
-	deadconn->fd = -1;
-	if (deadconn->handlerlist) {
-		aim_clearhandlers(deadconn);
-	}
-
-	return;
-}
-
-/**
- * aim_getconn_type - Find a connection of a specific type
- * @sess: Session to search
- * @type: Type of connection to look for
- *
- * Searches for a connection of the specified type in the
- * specified session.  Returns the first connection of that
- * type found.
- *
- * XXX except for RENDEZVOUS, all uses of this should be removed and
- * use aim_conn_findbygroup() instead.
- */
-aim_conn_t *aim_getconn_type(aim_session_t *sess, int type)
-{
-	aim_conn_t *cur;
-
-	for (cur = sess->connlist; cur; cur = cur->next) {
-		if ((cur->type == type) &&
-		    !(cur->status & AIM_CONN_STATUS_INPROGRESS)) {
-			break;
-		}
-	}
-
-	return cur;
-}
-
-aim_conn_t *aim_getconn_type_all(aim_session_t *sess, int type)
-{
-	aim_conn_t *cur;
-
-	for (cur = sess->connlist; cur; cur = cur->next) {
-		if (cur->type == type) {
-			break;
-		}
-	}
-
-	return cur;
-}
-
-/**
- * aim_newconn - Open a new connection
- * @sess: Session to create connection in
- * @type: Type of connection to create
- * @dest: Host to connect to (in "host:port" syntax)
- *
- * Opens a new connection to the specified dest host of specified
- * type, using the proxy settings if available.  If @host is %NULL,
- * the connection is allocated and returned, but no connection
- * is made.
- *
- * FIXME: Return errors in a more sane way.
- *
- */
-aim_conn_t *aim_newconn(aim_session_t *sess, int type, const char *dest)
-{
-	aim_conn_t *connstruct;
-
-	if (!(connstruct = aim_conn_getnext(sess))) {
-		return NULL;
-	}
-
-	connstruct->sessv = (void *) sess;
-	connstruct->type = type;
-
-	if (!dest) { /* just allocate a struct */
-		connstruct->fd = -1;
-		connstruct->status = 0;
-		return connstruct;
-	}
-
-	/* The code that used to be here was very broken */
-	g_return_val_if_reached(connstruct);
-
-	return connstruct;
-}
-
-/**
- * aim_conn_setlatency - Set a forced latency value for connection
- * @conn: Conn to set latency for
- * @newval: Number of seconds to force between transmits
- *
- * Causes @newval seconds to be spent between transmits on a connection.
- *
- * This is my lame attempt at overcoming not understanding the rate
- * limiting.
- *
- * XXX: This should really be replaced with something that scales and
- * backs off like the real rate limiting does.
- *
- */
-int aim_conn_setlatency(aim_conn_t *conn, int newval)
-{
-
-	if (!conn) {
-		return -1;
-	}
-
-	conn->forcedlatency = newval;
-	conn->lastactivity = 0; /* reset this just to make sure */
-
-	return 0;
-}
-
-/**
- * aim_session_init - Initializes a session structure
- * @sess: Session to initialize
- * @flags: Flags to use. Any of %AIM_SESS_FLAGS %OR'd together.
- * @debuglevel: Level of debugging output (zero is least)
- *
- * Sets up the initial values for a session.
- *
- */
-void aim_session_init(aim_session_t *sess, guint32 flags, int debuglevel)
-{
-
-	if (!sess) {
-		return;
-	}
-
-	memset(sess, 0, sizeof(aim_session_t));
-	aim_connrst(sess);
-	sess->queue_outgoing = NULL;
-	sess->queue_incoming = NULL;
-	aim_initsnachash(sess);
-	sess->msgcookies = NULL;
-	sess->snacid_next = 0x00000001;
-
-	sess->flags = 0;
-
-	sess->modlistv = NULL;
-
-	sess->ssi.received_data = 0;
-	sess->ssi.waiting_for_ack = 0;
-	sess->ssi.holding_queue = NULL;
-	sess->ssi.revision = 0;
-	sess->ssi.items = NULL;
-	sess->ssi.timestamp = (time_t) 0;
-
-	sess->locate.userinfo = NULL;
-	sess->locate.torequest = NULL;
-	sess->locate.requested = NULL;
-	sess->locate.waiting_for_response = FALSE;
-
-	sess->icq_info = NULL;
-	sess->authinfo = NULL;
-	sess->emailinfo = NULL;
-	sess->oft_info = NULL;
-
-	sess->flags |= AIM_SESS_FLAGS_SNACLOGIN;
-	sess->flags |= flags;
-
-	/*
-	 * This must always be set.  Default to the queue-based
-	 * version for back-compatibility.
-	 */
-	aim_tx_setenqueue(sess, AIM_TX_QUEUED, NULL);
-
-
-	/*
-	 * Register all the modules for this session...
-	 */
-	aim__registermodule(sess, misc_modfirst); /* load the catch-all first */
-	aim__registermodule(sess, general_modfirst);
-	aim__registermodule(sess, locate_modfirst);
-	aim__registermodule(sess, buddylist_modfirst);
-	aim__registermodule(sess, msg_modfirst);
-	aim__registermodule(sess, admin_modfirst);
-	aim__registermodule(sess, bos_modfirst);
-	aim__registermodule(sess, search_modfirst);
-	aim__registermodule(sess, stats_modfirst);
-	aim__registermodule(sess, chatnav_modfirst);
-	aim__registermodule(sess, chat_modfirst);
-	/* missing 0x0f - 0x12 */
-	aim__registermodule(sess, ssi_modfirst);
-	/* missing 0x14 */
-	aim__registermodule(sess, icq_modfirst);
-	/* missing 0x16 */
-	aim__registermodule(sess, auth_modfirst);
-
-	return;
-}
-
-/**
- * aim_session_kill - Deallocate a session
- * @sess: Session to kill
- *
- */
-void aim_session_kill(aim_session_t *sess)
-{
-	aim_cleansnacs(sess, -1);
-
-	aim_logoff(sess);
-
-	aim__shutdownmodules(sess);
-
-	return;
-}
-
-/*
- * XXX this is nearly as ugly as proxyconnect().
- */
-int aim_conn_completeconnect(aim_session_t *sess, aim_conn_t *conn)
-{
-	fd_set fds, wfds;
-	struct timeval tv;
-	int res, error = ETIMEDOUT;
-	aim_rxcallback_t userfunc;
-
-	if (!conn || (conn->fd == -1)) {
-		return -1;
-	}
-
-	if (!(conn->status & AIM_CONN_STATUS_INPROGRESS)) {
-		return -1;
-	}
-
-	FD_ZERO(&fds);
-	FD_SET(conn->fd, &fds);
-	FD_ZERO(&wfds);
-	FD_SET(conn->fd, &wfds);
-	tv.tv_sec = 0;
-	tv.tv_usec = 0;
-
-	if ((res = select(conn->fd + 1, &fds, &wfds, NULL, &tv)) == -1) {
-		error = errno;
-		aim_conn_close(conn);
-		errno = error;
-		return -1;
-	} else if (res == 0) {
-		return 0; /* hasn't really completed yet... */
-	}
-
-	if (FD_ISSET(conn->fd, &fds) || FD_ISSET(conn->fd, &wfds)) {
-		socklen_t len = sizeof(error);
-
-		if (getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
-			error = errno;
-		}
-	}
-
-	if (error) {
-		aim_conn_close(conn);
-		errno = error;
-		return -1;
-	}
-
-	sock_make_blocking(conn->fd);
-
-	conn->status &= ~AIM_CONN_STATUS_INPROGRESS;
-
-	if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE))) {
-		userfunc(sess, NULL, conn);
-	}
-
-	/* Flush out the queues if there was something waiting for this conn  */
-	aim_tx_flushqueue(sess);
-
-	return 0;
-}
-
-aim_session_t *aim_conn_getsess(aim_conn_t *conn)
-{
-
-	if (!conn) {
-		return NULL;
-	}
-
-	return (aim_session_t *) conn->sessv;
-}
-
-/*
- * aim_logoff()
- *
- * Closes -ALL- open connections.
- *
- */
-static int aim_logoff(aim_session_t *sess)
-{
-
-	aim_connrst(sess);  /* in case we want to connect again */
-
-	return 0;
-
-}
-
-/*
- * aim_flap_nop()
- *
- * No-op.  WinAIM 4.x sends these _every minute_ to keep
- * the connection alive.
- */
-int aim_flap_nop(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_frame_t *fr;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x05, 0))) {
-		return -ENOMEM;
-	}
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-
Index: protocols/oscar/icq.c
===================================================================
--- protocols/oscar/icq.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,387 +1,0 @@
-/*
- * Encapsulated ICQ.
- *
- */
-
-#include <aim.h>
-#include "icq.h"
-
-int aim_icq_reqofflinemsgs(aim_session_t *sess)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	int bslen;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) {
-		return -EINVAL;
-	}
-
-	bslen = 2 + 4 + 2 + 2;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid);
-
-	/* For simplicity, don't bother using a tlvlist */
-	aimbs_put16(&fr->data, 0x0001);
-	aimbs_put16(&fr->data, bslen);
-
-	aimbs_putle16(&fr->data, bslen - 2);
-	aimbs_putle32(&fr->data, atoi(sess->sn));
-	aimbs_putle16(&fr->data, 0x003c); /* I command thee. */
-	aimbs_putle16(&fr->data, snacid); /* eh. */
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-int aim_icq_ackofflinemsgs(aim_session_t *sess)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	int bslen;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) {
-		return -EINVAL;
-	}
-
-	bslen = 2 + 4 + 2 + 2;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid);
-
-	/* For simplicity, don't bother using a tlvlist */
-	aimbs_put16(&fr->data, 0x0001);
-	aimbs_put16(&fr->data, bslen);
-
-	aimbs_putle16(&fr->data, bslen - 2);
-	aimbs_putle32(&fr->data, atoi(sess->sn));
-	aimbs_putle16(&fr->data, 0x003e); /* I command thee. */
-	aimbs_putle16(&fr->data, snacid); /* eh. */
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-int aim_icq_getallinfo(aim_session_t *sess, const char *uin)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	int bslen;
-	struct aim_icq_info *info;
-
-	if (!uin || uin[0] < '0' || uin[0] > '9') {
-		return -EINVAL;
-	}
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0015))) {
-		return -EINVAL;
-	}
-
-	bslen = 2 + 4 + 2 + 2 + 2 + 4;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4 + bslen))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, 0x0015, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0015, 0x0002, 0x0000, snacid);
-
-	/* For simplicity, don't bother using a tlvlist */
-	aimbs_put16(&fr->data, 0x0001);
-	aimbs_put16(&fr->data, bslen);
-
-	aimbs_putle16(&fr->data, bslen - 2);
-	aimbs_putle32(&fr->data, atoi(sess->sn));
-	aimbs_putle16(&fr->data, 0x07d0); /* I command thee. */
-	aimbs_putle16(&fr->data, snacid); /* eh. */
-	aimbs_putle16(&fr->data, 0x04b2); /* shrug. */
-	aimbs_putle32(&fr->data, atoi(uin));
-
-	aim_tx_enqueue(sess, fr);
-
-	/* Keep track of this request and the ICQ number and request ID */
-	info = g_new0(struct aim_icq_info, 1);
-	info->reqid = snacid;
-	info->uin = atoi(uin);
-	info->next = sess->icq_info;
-	sess->icq_info = info;
-
-	return 0;
-}
-
-static void aim_icq_freeinfo(struct aim_icq_info *info)
-{
-	int i;
-
-	if (!info) {
-		return;
-	}
-	g_free(info->nick);
-	g_free(info->first);
-	g_free(info->last);
-	g_free(info->email);
-	g_free(info->homecity);
-	g_free(info->homestate);
-	g_free(info->homephone);
-	g_free(info->homefax);
-	g_free(info->homeaddr);
-	g_free(info->mobile);
-	g_free(info->homezip);
-	g_free(info->personalwebpage);
-	if (info->email2) {
-		for (i = 0; i < info->numaddresses; i++) {
-			g_free(info->email2[i]);
-		}
-	}
-	g_free(info->email2);
-	g_free(info->workcity);
-	g_free(info->workstate);
-	g_free(info->workphone);
-	g_free(info->workfax);
-	g_free(info->workaddr);
-	g_free(info->workzip);
-	g_free(info->workcompany);
-	g_free(info->workdivision);
-	g_free(info->workposition);
-	g_free(info->workwebpage);
-	g_free(info->info);
-	g_free(info);
-}
-
-/**
- * Subtype 0x0003 - Response to 0x0015/0x002, contains an ICQesque packet.
- */
-static int icqresponse(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_tlvlist_t *tl;
-	aim_tlv_t *datatlv;
-	aim_bstream_t qbs;
-	guint16 cmd, reqid;
-
-	if (!(tl = aim_readtlvchain(bs)) || !(datatlv = aim_gettlv(tl, 0x0001, 1))) {
-		aim_freetlvchain(&tl);
-		imcb_error(sess->aux_data, "corrupt ICQ response\n");
-		return 0;
-	}
-
-	aim_bstream_init(&qbs, datatlv->value, datatlv->length);
-
-	aimbs_getle16(&qbs); /* cmdlen */
-	aimbs_getle32(&qbs); /* ouruin */
-	cmd = aimbs_getle16(&qbs);
-	reqid = aimbs_getle16(&qbs);
-
-	if (cmd == 0x0041) { /* offline message */
-		guint16 msglen;
-		struct aim_icq_offlinemsg msg;
-		aim_rxcallback_t userfunc;
-
-		memset(&msg, 0, sizeof(msg));
-
-		msg.sender = aimbs_getle32(&qbs);
-		msg.year = aimbs_getle16(&qbs);
-		msg.month = aimbs_getle8(&qbs);
-		msg.day = aimbs_getle8(&qbs);
-		msg.hour = aimbs_getle8(&qbs);
-		msg.minute = aimbs_getle8(&qbs);
-		msg.type = aimbs_getle16(&qbs);
-		msglen = aimbs_getle16(&qbs);
-		msg.msg = aimbs_getstr(&qbs, msglen);
-
-		if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSG))) {
-			ret = userfunc(sess, rx, &msg);
-		}
-
-		g_free(msg.msg);
-
-	} else if (cmd == 0x0042) {
-		aim_rxcallback_t userfunc;
-
-		if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSGCOMPLETE))) {
-			ret = userfunc(sess, rx);
-		}
-	} else if (cmd == 0x07da) { /* information */
-		guint16 subtype;
-		struct aim_icq_info *info;
-		aim_rxcallback_t userfunc;
-
-		subtype = aimbs_getle16(&qbs);
-		aim_bstream_advance(&qbs, 1); /* 0x0a */
-
-		/* find another data from the same request */
-		for (info = sess->icq_info; info && (info->reqid != reqid); info = info->next) {
-			;
-		}
-
-		if (!info) {
-			info = g_new0(struct aim_icq_info, 1);
-			info->reqid = reqid;
-			info->next = sess->icq_info;
-			sess->icq_info = info;
-		}
-
-		switch (subtype) {
-		case 0x00a0: {         /* hide ip status */
-			/* nothing */
-		} break;
-		case 0x00aa: {         /* password change status */
-			/* nothing */
-		} break;
-		case 0x00c8: {         /* general and "home" information */
-			info->nick = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->first = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->last = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->email = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->homecity = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->homestate = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->homephone = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->homefax = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->homeaddr = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->mobile = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->homezip = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->homecountry = aimbs_getle16(&qbs);
-			/* 0x0a 00 02 00 */
-			/* 1 byte timezone? */
-			/* 1 byte hide email flag? */
-		} break;
-		case 0x00dc: {         /* personal information */
-			info->age = aimbs_getle8(&qbs);
-			info->unknown = aimbs_getle8(&qbs);
-			info->gender = aimbs_getle8(&qbs);
-			info->personalwebpage = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->birthyear = aimbs_getle16(&qbs);
-			info->birthmonth = aimbs_getle8(&qbs);
-			info->birthday = aimbs_getle8(&qbs);
-			info->language1 = aimbs_getle8(&qbs);
-			info->language2 = aimbs_getle8(&qbs);
-			info->language3 = aimbs_getle8(&qbs);
-			/* 0x00 00 01 00 00 01 00 00 00 00 00 */
-		} break;
-		case 0x00d2: {         /* work information */
-			info->workcity = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->workstate = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->workphone = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->workfax = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->workaddr = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->workzip = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->workcountry = aimbs_getle16(&qbs);
-			info->workcompany = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->workdivision = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->workposition = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			aim_bstream_advance(&qbs, 2);                                  /* 0x01 00 */
-			info->workwebpage = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-		} break;
-		case 0x00e6: {         /* additional personal information */
-			info->info = aimbs_getstr(&qbs, aimbs_getle16(&qbs) - 1);
-		} break;
-		case 0x00eb: {         /* email address(es) */
-			int i;
-			info->numaddresses = aimbs_getle16(&qbs);
-			info->email2 = g_new0(char *, info->numaddresses);
-			for (i = 0; i < info->numaddresses; i++) {
-				info->email2[i] = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-				if (i + 1 != info->numaddresses) {
-					aim_bstream_advance(&qbs, 1);                                  /* 0x00 */
-				}
-			}
-		} break;
-		case 0x00f0: {         /* personal interests */
-		} break;
-		case 0x00fa: {         /* past background and current organizations */
-		} break;
-		case 0x0104: {         /* alias info */
-			info->nick = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->first = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->last = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			aim_bstream_advance(&qbs, aimbs_getle16(&qbs));
-			/* email address? */
-			/* Then 0x00 02 00 */
-		} break;
-		case 0x010e: {         /* unknown */
-			/* 0x00 00 */
-		} break;
-
-		case 0x019a: {         /* simple info */
-			aim_bstream_advance(&qbs, 2);
-			info->uin = aimbs_getle32(&qbs);
-			info->nick = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->first = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->last = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			info->email = aimbs_getstr(&qbs, aimbs_getle16(&qbs));
-			/* Then 0x00 02 00 00 00 00 00 */
-		} break;
-		} /* End switch statement */
-
-
-		if (!(snac->flags & 0x0001)) {
-			if (subtype != 0x0104) {
-				if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_INFO))) {
-					ret = userfunc(sess, rx, info);
-				}
-			}
-
-			/* Bitlbee - not supported, yet
-			if (info->uin && info->nick)
-			        if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_ALIAS)))
-			                ret = userfunc(sess, rx, info);
-			*/
-
-			if (sess->icq_info == info) {
-				sess->icq_info = info->next;
-			} else {
-				struct aim_icq_info *cur;
-				for (cur = sess->icq_info; (cur->next && (cur->next != info)); cur = cur->next) {
-					;
-				}
-				if (cur->next) {
-					cur->next = cur->next->next;
-				}
-			}
-			aim_icq_freeinfo(info);
-		}
-	}
-
-	aim_freetlvchain(&tl);
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0003) {
-		return icqresponse(sess, mod, rx, snac, bs);
-	}
-
-	return 0;
-}
-
-int icq_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x0015;
-	mod->version = 0x0001;
-	mod->toolid = 0x0110;
-	mod->toolversion = 0x047c;
-	mod->flags = 0;
-	strncpy(mod->name, "icq", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
-
-
Index: protocols/oscar/icq.h
===================================================================
--- protocols/oscar/icq.h	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,97 +1,0 @@
-#ifndef __OSCAR_ICQ_H__
-#define __OSCAR_ICQ_H__
-
-#define AIM_CB_FAM_ICQ 0x0015
-
-/*
- * SNAC Family: ICQ
- *
- * Most of these are actually special.
- */
-#define AIM_CB_ICQ_ERROR 0x0001
-#define AIM_CB_ICQ_OFFLINEMSG 0x00f0
-#define AIM_CB_ICQ_OFFLINEMSGCOMPLETE 0x00f1
-#define AIM_CB_ICQ_SIMPLEINFO 0x00f2
-#define AIM_CB_ICQ_INFO 0x00f2 /* just transitional */
-#define AIM_CB_ICQ_DEFAULT 0xffff
-
-struct aim_icq_offlinemsg {
-	guint32 sender;
-	guint16 year;
-	guint8 month, day, hour, minute;
-	guint16 type;
-	char *msg;
-};
-
-struct aim_icq_simpleinfo {
-	guint32 uin;
-	char *nick;
-	char *first;
-	char *last;
-	char *email;
-};
-
-struct aim_icq_info {
-	gushort reqid;
-
-	/* simple */
-	guint32 uin;
-
-	/* general and "home" information (0x00c8) */
-	char *nick;
-	char *first;
-	char *last;
-	char *email;
-	char *homecity;
-	char *homestate;
-	char *homephone;
-	char *homefax;
-	char *homeaddr;
-	char *mobile;
-	char *homezip;
-	gushort homecountry;
-/*      guchar timezone;
-        guchar hideemail; */
-
-	/* personal (0x00dc) */
-	guchar age;
-	guchar unknown;
-	guchar gender;
-	char *personalwebpage;
-	gushort birthyear;
-	guchar birthmonth;
-	guchar birthday;
-	guchar language1;
-	guchar language2;
-	guchar language3;
-
-	/* work (0x00d2) */
-	char *workcity;
-	char *workstate;
-	char *workphone;
-	char *workfax;
-	char *workaddr;
-	char *workzip;
-	gushort workcountry;
-	char *workcompany;
-	char *workdivision;
-	char *workposition;
-	char *workwebpage;
-
-	/* additional personal information (0x00e6) */
-	char *info;
-
-	/* email (0x00eb) */
-	gushort numaddresses;
-	char **email2;
-
-	/* we keep track of these in a linked list because we're 1337 */
-	struct aim_icq_info *next;
-};
-
-
-int aim_icq_reqofflinemsgs(aim_session_t *sess);
-int aim_icq_ackofflinemsgs(aim_session_t *sess);
-int aim_icq_getallinfo(aim_session_t *sess, const char *uin);
-
-#endif /* __OSCAR_ICQ_H__ */
Index: protocols/oscar/im.c
===================================================================
--- protocols/oscar/im.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,1561 +1,0 @@
-/*
- *  aim_im.c
- *
- *  The routines for sending/receiving Instant Messages.
- *
- *  Note the term ICBM (Inter-Client Basic Message) which blankets
- *  all types of genericly routed through-server messages.  Within
- *  the ICBM types (family 4), a channel is defined.  Each channel
- *  represents a different type of message.  Channel 1 is used for
- *  what would commonly be called an "instant message".  Channel 2
- *  is used for negotiating "rendezvous".  These transactions end in
- *  something more complex happening, such as a chat invitation, or
- *  a file transfer.
- *
- *  In addition to the channel, every ICBM contains a cookie.  For
- *  standard IMs, these are only used for error messages.  However,
- *  the more complex rendezvous messages make suitably more complex
- *  use of this field.
- *
- */
-
-#include <aim.h>
-#include "im.h"
-#include "info.h"
-
-/*
- * Send an ICBM (instant message).
- *
- *
- * Possible flags:
- *   AIM_IMFLAGS_AWAY  -- Marks the message as an autoresponse
- *   AIM_IMFLAGS_ACK   -- Requests that the server send an ack
- *                        when the message is received (of type 0x0004/0x000c)
- *   AIM_IMFLAGS_OFFLINE--If destination is offline, store it until they are
- *                        online (probably ICQ only).
- *   AIM_IMFLAGS_UNICODE--Instead of ASCII7, the passed message is
- *                        made up of UNICODE duples.  If you set
- *                        this, you'd better be damn sure you know
- *                        what you're doing.
- *   AIM_IMFLAGS_ISO_8859_1 -- The message contains the ASCII8 subset
- *                        known as ISO-8859-1.
- *
- * Generally, you should use the lowest encoding possible to send
- * your message.  If you only use basic punctuation and the generic
- * Latin alphabet, use ASCII7 (no flags).  If you happen to use non-ASCII7
- * characters, but they are all clearly defined in ISO-8859-1, then
- * use that.  Keep in mind that not all characters in the PC ASCII8
- * character set are defined in the ISO standard. For those cases (most
- * notably when the (r) symbol is used), you must use the full UNICODE
- * encoding for your message.  In UNICODE mode, _all_ characters must
- * occupy 16bits, including ones that are not special.  (Remember that
- * the first 128 UNICODE symbols are equivalent to ASCII7, however they
- * must be prefixed with a zero high order byte.)
- *
- * I strongly discourage the use of UNICODE mode, mainly because none
- * of the clients I use can parse those messages (and besides that,
- * wchars are difficult and non-portable to handle in most UNIX environments).
- * If you really need to include special characters, use the HTML UNICODE
- * entities.  These are of the form &#2026; where 2026 is the hex
- * representation of the UNICODE index (in this case, UNICODE
- * "Horizontal Ellipsis", or 133 in in ASCII8).
- *
- * Implementation note:  Since this is one of the most-used functions
- * in all of libfaim, it is written with performance in mind.  As such,
- * it is not as clear as it could be in respect to how this message is
- * supposed to be laid out. Most obviously, tlvlists should be used
- * instead of writing out the bytes manually.
- *
- * XXX more precise verification that we never send SNACs larger than 8192
- * XXX check SNAC size for multipart
- *
- */
-int aim_send_im_ext(aim_session_t *sess, struct aim_sendimext_args *args)
-{
-	static const guint8 deffeatures[] = {
-		0x01, 0x01, 0x01, 0x02
-	};
-	aim_conn_t *conn;
-	int i, msgtlvlen;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) {
-		return -EINVAL;
-	}
-
-	if (!args) {
-		return -EINVAL;
-	}
-
-	if (args->flags & AIM_IMFLAGS_MULTIPART) {
-		if (args->mpmsg->numparts <= 0) {
-			return -EINVAL;
-		}
-	} else {
-		if (!args->msg || (args->msglen <= 0)) {
-			return -EINVAL;
-		}
-
-		if (args->msglen >= MAXMSGLEN) {
-			return -E2BIG;
-		}
-	}
-
-	/* Painfully calculate the size of the message TLV */
-	msgtlvlen = 1 + 1; /* 0501 */
-
-	if (args->flags & AIM_IMFLAGS_CUSTOMFEATURES) {
-		msgtlvlen += 2 + args->featureslen;
-	} else {
-		msgtlvlen += 2 + sizeof(deffeatures);
-	}
-
-	if (args->flags & AIM_IMFLAGS_MULTIPART) {
-		aim_mpmsg_section_t *sec;
-
-		for (sec = args->mpmsg->parts; sec; sec = sec->next) {
-			msgtlvlen += 2 /* 0101 */ + 2 /* block len */;
-			msgtlvlen += 4 /* charset */ + sec->datalen;
-		}
-
-	} else {
-		msgtlvlen += 2 /* 0101 */ + 2 /* block len */;
-		msgtlvlen += 4 /* charset */ + args->msglen;
-	}
-
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, msgtlvlen + 128))) {
-		return -ENOMEM;
-	}
-
-	/* XXX should be optional */
-	snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, args->destsn, strlen(args->destsn) + 1);
-	aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid);
-
-	/*
-	 * Generate a random message cookie
-	 *
-	 * We could cache these like we do SNAC IDs.  (In fact, it
-	 * might be a good idea.)  In the message error functions,
-	 * the 8byte message cookie is returned as well as the
-	 * SNAC ID.
-	 *
-	 */
-	for (i = 0; i < 8; i++) {
-		aimbs_put8(&fr->data, (guint8) rand());
-	}
-
-	/*
-	 * Channel ID
-	 */
-	aimbs_put16(&fr->data, 0x0001);
-
-	/*
-	 * Destination SN (prepended with byte length)
-	 */
-	aimbs_put8(&fr->data, strlen(args->destsn));
-	aimbs_putraw(&fr->data, (guint8 *) args->destsn, strlen(args->destsn));
-
-	/*
-	 * Message TLV (type 2).
-	 */
-	aimbs_put16(&fr->data, 0x0002);
-	aimbs_put16(&fr->data, msgtlvlen);
-
-	/*
-	 * Features
-	 *
-	 */
-	aimbs_put8(&fr->data, 0x05);
-	aimbs_put8(&fr->data, 0x01);
-
-	if (args->flags & AIM_IMFLAGS_CUSTOMFEATURES) {
-		aimbs_put16(&fr->data, args->featureslen);
-		aimbs_putraw(&fr->data, args->features, args->featureslen);
-	} else {
-		aimbs_put16(&fr->data, sizeof(deffeatures));
-		aimbs_putraw(&fr->data, deffeatures, sizeof(deffeatures));
-	}
-
-	if (args->flags & AIM_IMFLAGS_MULTIPART) {
-		aim_mpmsg_section_t *sec;
-
-		for (sec = args->mpmsg->parts; sec; sec = sec->next) {
-			aimbs_put16(&fr->data, 0x0101);
-			aimbs_put16(&fr->data, sec->datalen + 4);
-			aimbs_put16(&fr->data, sec->charset);
-			aimbs_put16(&fr->data, sec->charsubset);
-			aimbs_putraw(&fr->data, sec->data, sec->datalen);
-		}
-
-	} else {
-
-		aimbs_put16(&fr->data, 0x0101);
-
-		/*
-		 * Message block length.
-		 */
-		aimbs_put16(&fr->data, args->msglen + 0x04);
-
-		/*
-		 * Character set.
-		 */
-		if (args->flags & AIM_IMFLAGS_CUSTOMCHARSET) {
-
-			aimbs_put16(&fr->data, args->charset);
-			aimbs_put16(&fr->data, args->charsubset);
-
-		} else {
-			if (args->flags & AIM_IMFLAGS_UNICODE) {
-				aimbs_put16(&fr->data, 0x0002);
-			} else if (args->flags & AIM_IMFLAGS_ISO_8859_1) {
-				aimbs_put16(&fr->data, 0x0003);
-			} else {
-				aimbs_put16(&fr->data, 0x0000);
-			}
-
-			aimbs_put16(&fr->data, 0x0000);
-		}
-
-		/*
-		 * Message.  Not terminated.
-		 */
-		aimbs_putraw(&fr->data, (guint8 *) args->msg, args->msglen);
-	}
-
-	/*
-	 * Set the Request Acknowledge flag.
-	 */
-	if (args->flags & AIM_IMFLAGS_ACK) {
-		aimbs_put16(&fr->data, 0x0003);
-		aimbs_put16(&fr->data, 0x0000);
-	}
-
-	/*
-	 * Set the Autoresponse flag.
-	 */
-	if (args->flags & AIM_IMFLAGS_AWAY) {
-		aimbs_put16(&fr->data, 0x0004);
-		aimbs_put16(&fr->data, 0x0000);
-	}
-
-	if (args->flags & AIM_IMFLAGS_OFFLINE) {
-		aimbs_put16(&fr->data, 0x0006);
-		aimbs_put16(&fr->data, 0x0000);
-	}
-
-	/*
-	 * Set the I HAVE A REALLY PURTY ICON flag.
-	 */
-	if (args->flags & AIM_IMFLAGS_HASICON) {
-		aimbs_put16(&fr->data, 0x0008);
-		aimbs_put16(&fr->data, 0x000c);
-		aimbs_put32(&fr->data, args->iconlen);
-		aimbs_put16(&fr->data, 0x0001);
-		aimbs_put16(&fr->data, args->iconsum);
-		aimbs_put32(&fr->data, args->iconstamp);
-	}
-
-	/*
-	 * Set the Buddy Icon Requested flag.
-	 */
-	if (args->flags & AIM_IMFLAGS_BUDDYREQ) {
-		aimbs_put16(&fr->data, 0x0009);
-		aimbs_put16(&fr->data, 0x0000);
-	}
-
-	aim_tx_enqueue(sess, fr);
-
-	if (!(sess->flags & AIM_SESS_FLAGS_DONTTIMEOUTONICBM)) {
-		aim_cleansnacs(sess, 60); /* clean out SNACs over 60sec old */
-
-	}
-	return 0;
-}
-
-/*
- * Simple wrapper for aim_send_im_ext()
- *
- * You cannot use aim_send_im if you need the HASICON flag.  You must
- * use aim_send_im_ext directly for that.
- *
- * aim_send_im also cannot be used if you require UNICODE messages, because
- * that requires an explicit message length.  Use aim_send_im_ext().
- *
- */
-int aim_send_im(aim_session_t *sess, const char *destsn, guint16 flags, const char *msg)
-{
-	struct aim_sendimext_args args;
-
-	args.destsn = destsn;
-	args.flags = flags;
-	args.msg = msg;
-	args.msglen = strlen(msg);
-
-	/* Make these don't get set by accident -- they need aim_send_im_ext */
-	args.flags &= ~(AIM_IMFLAGS_CUSTOMFEATURES | AIM_IMFLAGS_HASICON | AIM_IMFLAGS_MULTIPART);
-
-	return aim_send_im_ext(sess, &args);
-}
-
-/**
- * answers status message requests
- * @param sess the oscar session
- * @param sender the guy whos asking
- * @param cookie message id which we are answering for
- * @param message away message
- * @param state our current away state the way icq requests it (0xE8 for away, 0xE9 occupied, ...)
- * @return 0 if no error
- */
-int aim_send_im_ch2_statusmessage(aim_session_t *sess, const char *sender, const guint8 *cookie,
-                                  const char *message, const guint8 state, const guint16 dc)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) {
-		return -EINVAL;
-	}
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02,
-	                      10 + 8 + 2 + 1 + strlen(sender) + 2 + 0x1d + 0x10 + 9 + strlen(message) + 1))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, 0x0004, 0x000b, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0004, 0x000b, 0x0000, snacid);
-
-	aimbs_putraw(&fr->data, cookie, 8);
-
-	aimbs_put16(&fr->data, 0x0002); /* channel */
-	aimbs_put8(&fr->data, strlen(sender));
-	aimbs_putraw(&fr->data, (guint8 *) sender, strlen(sender));
-
-	aimbs_put16(&fr->data, 0x0003); /* reason: channel specific */
-
-	aimbs_putle16(&fr->data, 0x001b); /* length of data SEQ1 */
-	aimbs_putle16(&fr->data, 0x0008); /* protocol version */
-
-	aimbs_putle32(&fr->data, 0x0000); /* no plugin -> 16 times 0x00 */
-	aimbs_putle32(&fr->data, 0x0000);
-	aimbs_putle32(&fr->data, 0x0000);
-	aimbs_putle32(&fr->data, 0x0000);
-
-	aimbs_putle16(&fr->data, 0x0000); /* unknown */
-	aimbs_putle32(&fr->data, 0x0003); /* client features */
-	aimbs_putle8(&fr->data, 0x00); /* unknown */
-	aimbs_putle16(&fr->data, dc); /* Sequence number?  XXX - This should decrement by 1 with each request */
-	/* end of SEQ1 */
-
-	aimbs_putle16(&fr->data, 0x000e); /* Length of SEQ2 */
-	aimbs_putle16(&fr->data, dc); /* Sequence number? same as above
-	                               * XXX - This should decrement by 1 with each request */
-	aimbs_putle32(&fr->data, 0x00000000); /* Unknown */
-	aimbs_putle32(&fr->data, 0x00000000); /* Unknown */
-	aimbs_putle32(&fr->data, 0x00000000); /* Unknown */
-	/* end of SEQ2 */
-
-	/* now for the real fun */
-	aimbs_putle8(&fr->data, state); /* away state */
-	aimbs_putle8(&fr->data, 0x03); /* msg-flag: 03 for states */
-	aimbs_putle16(&fr->data, 0x0000); /* status code ? */
-	aimbs_putle16(&fr->data, 0x0000); /* priority code */
-	aimbs_putle16(&fr->data, strlen(message) + 1); /* message length + termination */
-	aimbs_putraw(&fr->data, (guint8 *) message, strlen(message) + 1); /* null terminated string */
-
-	aim_tx_enqueue(sess, fr);
-
-
-	return 0;
-}
-
-
-static int outgoingim(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int i, ret = 0;
-	aim_rxcallback_t userfunc;
-	guint16 channel;
-	aim_tlvlist_t *tlvlist;
-	char *sn;
-	int snlen;
-	guint16 icbmflags = 0;
-	guint8 flag1 = 0, flag2 = 0;
-	char *msg = NULL;
-	aim_tlv_t *msgblock;
-
-	/* ICBM Cookie. */
-	for (i = 0; i < 8; i++) {
-		aimbs_get8(bs);
-	}
-
-	/* Channel ID */
-	channel = aimbs_get16(bs);
-
-	if (channel != 0x01) {
-		imcb_error(sess->aux_data, "icbm: ICBM received on unsupported channel.  Ignoring.");
-		return 0;
-	}
-
-	snlen = aimbs_get8(bs);
-	sn = aimbs_getstr(bs, snlen);
-
-	tlvlist = aim_readtlvchain(bs);
-
-	if (aim_gettlv(tlvlist, 0x0003, 1)) {
-		icbmflags |= AIM_IMFLAGS_ACK;
-	}
-	if (aim_gettlv(tlvlist, 0x0004, 1)) {
-		icbmflags |= AIM_IMFLAGS_AWAY;
-	}
-
-	if ((msgblock = aim_gettlv(tlvlist, 0x0002, 1))) {
-		aim_bstream_t mbs;
-		int featurelen, msglen;
-
-		aim_bstream_init(&mbs, msgblock->value, msgblock->length);
-
-		aimbs_get8(&mbs);
-		aimbs_get8(&mbs);
-		for (featurelen = aimbs_get16(&mbs); featurelen; featurelen--) {
-			aimbs_get8(&mbs);
-		}
-		aimbs_get8(&mbs);
-		aimbs_get8(&mbs);
-
-		msglen = aimbs_get16(&mbs) - 4; /* final block length */
-
-		flag1 = aimbs_get16(&mbs);
-		flag2 = aimbs_get16(&mbs);
-
-		msg = aimbs_getstr(&mbs, msglen);
-	}
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, channel, sn, msg, icbmflags, flag1, flag2);
-	}
-
-	g_free(sn);
-	aim_freetlvchain(&tlvlist);
-
-	return ret;
-}
-
-/*
- * Ahh, the joys of nearly ridiculous over-engineering.
- *
- * Not only do AIM ICBM's support multiple channels.  Not only do they
- * support multiple character sets.  But they support multiple character
- * sets / encodings within the same ICBM.
- *
- * These multipart messages allow for complex space savings techniques, which
- * seem utterly unnecessary by today's standards.  In fact, there is only
- * one client still in popular use that still uses this method: AOL for the
- * Macintosh, Version 5.0.  Obscure, yes, I know.
- *
- * In modern (non-"legacy") clients, if the user tries to send a character
- * that is not ISO-8859-1 or ASCII, the client will send the entire message
- * as UNICODE, meaning that every character in the message will occupy the
- * full 16 bit UNICODE field, even if the high order byte would be zero.
- * Multipart messages prevent this wasted space by allowing the client to
- * only send the characters in UNICODE that need to be sent that way, and
- * the rest of the message can be sent in whatever the native character
- * set is (probably ASCII).
- *
- * An important note is that sections will be displayed in the order that
- * they appear in the ICBM.  There is no facility for merging or rearranging
- * sections at run time.  So if you have, say, ASCII then UNICODE then ASCII,
- * you must supply two ASCII sections with a UNICODE in the middle, and incur
- * the associated overhead.
- *
- * Normally I would have laughed and given a firm 'no' to supporting this
- * seldom-used feature, but something is attracting me to it.  In the future,
- * it may be possible to abuse this to send mixed-media messages to other
- * open source clients (like encryption or something) -- see faimtest for
- * examples of how to do this.
- *
- * I would definitely recommend avoiding this feature unless you really
- * know what you are doing, and/or you have something neat to do with it.
- *
- */
-int aim_mpmsg_init(aim_session_t *sess, aim_mpmsg_t *mpm)
-{
-
-	memset(mpm, 0, sizeof(aim_mpmsg_t));
-
-	return 0;
-}
-
-static int mpmsg_addsection(aim_session_t *sess, aim_mpmsg_t *mpm, guint16 charset, guint16 charsubset, guint8 *data,
-                            guint16 datalen)
-{
-	aim_mpmsg_section_t *sec;
-
-	if (!(sec = g_new0(aim_mpmsg_section_t, 1))) {
-		return -1;
-	}
-
-	sec->charset = charset;
-	sec->charsubset = charsubset;
-	sec->data = data;
-	sec->datalen = datalen;
-	sec->next = NULL;
-
-	if (!mpm->parts) {
-		mpm->parts = sec;
-	} else {
-		aim_mpmsg_section_t *cur;
-
-		for (cur = mpm->parts; cur->next; cur = cur->next) {
-			;
-		}
-		cur->next = sec;
-	}
-
-	mpm->numparts++;
-
-	return 0;
-}
-
-void aim_mpmsg_free(aim_session_t *sess, aim_mpmsg_t *mpm)
-{
-	aim_mpmsg_section_t *cur;
-
-	for (cur = mpm->parts; cur; ) {
-		aim_mpmsg_section_t *tmp;
-
-		tmp = cur->next;
-		g_free(cur->data);
-		g_free(cur);
-		cur = tmp;
-	}
-
-	mpm->numparts = 0;
-	mpm->parts = NULL;
-
-	return;
-}
-
-/*
- * Start by building the multipart structures, then pick the first
- * human-readable section and stuff it into args->msg so no one gets
- * suspicious.
- *
- */
-static int incomingim_ch1_parsemsgs(aim_session_t *sess, guint8 *data, int len, struct aim_incomingim_ch1_args *args)
-{
-	static const guint16 charsetpri[] = {
-		0x0000, /* ASCII first */
-		0x0003, /* then ISO-8859-1 */
-		0x0002, /* UNICODE as last resort */
-	};
-	static const int charsetpricount = 3;
-	int i;
-	aim_bstream_t mbs;
-	aim_mpmsg_section_t *sec;
-
-	aim_bstream_init(&mbs, data, len);
-
-	while (aim_bstream_empty(&mbs)) {
-		guint16 msglen, flag1, flag2;
-		char *msgbuf;
-
-		aimbs_get8(&mbs); /* 01 */
-		aimbs_get8(&mbs); /* 01 */
-
-		/* Message string length, including character set info. */
-		msglen = aimbs_get16(&mbs);
-
-		/* Character set info */
-		flag1 = aimbs_get16(&mbs);
-		flag2 = aimbs_get16(&mbs);
-
-		/* Message. */
-		msglen -= 4;
-
-		/*
-		 * For now, we don't care what the encoding is.  Just copy
-		 * it into a multipart struct and deal with it later. However,
-		 * always pad the ending with a NULL.  This makes it easier
-		 * to treat ASCII sections as strings.  It won't matter for
-		 * UNICODE or binary data, as you should never read past
-		 * the specified data length, which will not include the pad.
-		 *
-		 * XXX There's an API bug here.  For sending, the UNICODE is
-		 * given in host byte order (aim_mpmsg_addunicode), but here
-		 * the received messages are given in network byte order.
-		 *
-		 */
-		msgbuf = aimbs_getstr(&mbs, msglen);
-		mpmsg_addsection(sess, &args->mpmsg, flag1, flag2, (guint8 *) msgbuf, (guint16) msglen);
-
-	} /* while */
-
-	args->icbmflags |= AIM_IMFLAGS_MULTIPART; /* always set */
-
-	/*
-	 * Clients that support multiparts should never use args->msg, as it
-	 * will point to an arbitrary section.
-	 *
-	 * Here, we attempt to provide clients that do not support multipart
-	 * messages with something to look at -- hopefully a human-readable
-	 * string.  But, failing that, a UNICODE message, or nothing at all.
-	 *
-	 * Which means that even if args->msg is NULL, it does not mean the
-	 * message was blank.
-	 *
-	 */
-	for (i = 0; i < charsetpricount; i++) {
-		for (sec = args->mpmsg.parts; sec; sec = sec->next) {
-
-			if (sec->charset != charsetpri[i]) {
-				continue;
-			}
-
-			/* Great. We found one.  Fill it in. */
-			args->charset = sec->charset;
-			args->charsubset = sec->charsubset;
-			args->icbmflags |= AIM_IMFLAGS_CUSTOMCHARSET;
-
-			/* Set up the simple flags */
-			if (args->charset == 0x0000) {
-				; /* ASCII */
-			} else if (args->charset == 0x0002) {
-				args->icbmflags |= AIM_IMFLAGS_UNICODE;
-			} else if (args->charset == 0x0003) {
-				args->icbmflags |= AIM_IMFLAGS_ISO_8859_1;
-			} else if (args->charset == 0xffff) {
-				; /* no encoding (yeep!) */
-
-			}
-			if (args->charsubset == 0x0000) {
-				; /* standard subencoding? */
-			} else if (args->charsubset == 0x000b) {
-				args->icbmflags |= AIM_IMFLAGS_SUBENC_MACINTOSH;
-			} else if (args->charsubset == 0xffff) {
-				; /* no subencoding */
-			}
-#if 0
-			/* XXX this isn't really necessary... */
-			if (((args.flag1 != 0x0000) &&
-			     (args.flag1 != 0x0002) &&
-			     (args.flag1 != 0x0003) &&
-			     (args.flag1 != 0xffff)) ||
-			    ((args.flag2 != 0x0000) &&
-			     (args.flag2 != 0x000b) &&
-			     (args.flag2 != 0xffff))) {
-				faimdprintf(sess, 0, "icbm: **warning: encoding flags are being used! {%04x, %04x}\n",
-				            args.flag1, args.flag2);
-			}
-#endif
-
-			args->msg = (char *) sec->data;
-			args->msglen = sec->datalen;
-
-			return 0;
-		}
-	}
-
-	/* No human-readable sections found.  Oh well. */
-	args->charset = args->charsubset = 0xffff;
-	args->msg = NULL;
-	args->msglen = 0;
-
-	return 0;
-}
-
-static int incomingim_ch1(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, guint16 channel,
-                          aim_userinfo_t *userinfo, aim_bstream_t *bs, guint8 *cookie)
-{
-	guint16 type, length;
-	aim_rxcallback_t userfunc;
-	int ret = 0;
-	struct aim_incomingim_ch1_args args;
-	int endpos;
-
-	memset(&args, 0, sizeof(args));
-
-	aim_mpmsg_init(sess, &args.mpmsg);
-
-	/*
-	 * This used to be done using tlvchains.  For performance reasons,
-	 * I've changed it to process the TLVs in-place.  This avoids lots
-	 * of per-IM memory allocations.
-	 */
-	while (aim_bstream_empty(bs)) {
-
-		type = aimbs_get16(bs);
-		length = aimbs_get16(bs);
-
-		endpos = aim_bstream_curpos(bs) + length;
-
-		if (type == 0x0002) { /* Message Block */
-
-			/*
-			 * This TLV consists of the following:
-			 *   - 0501 -- Unknown
-			 *   - Features: Don't know how to interpret these
-			 *   - 0101 -- Unknown
-			 *   - Message
-			 *
-			 */
-
-			aimbs_get8(bs); /* 05 */
-			aimbs_get8(bs); /* 01 */
-
-			args.featureslen = aimbs_get16(bs);
-			/* XXX XXX this is all evil! */
-			args.features = bs->data + bs->offset;
-			aim_bstream_advance(bs, args.featureslen);
-			args.icbmflags |= AIM_IMFLAGS_CUSTOMFEATURES;
-
-			/*
-			 * The rest of the TLV contains one or more message
-			 * blocks...
-			 */
-			incomingim_ch1_parsemsgs(sess, bs->data + bs->offset /* XXX evil!!! */,
-			                         length - 2 - 2 - args.featureslen, &args);
-
-		} else if (type == 0x0003) { /* Server Ack Requested */
-
-			args.icbmflags |= AIM_IMFLAGS_ACK;
-
-		} else if (type == 0x0004) { /* Message is Auto Response */
-
-			args.icbmflags |= AIM_IMFLAGS_AWAY;
-
-		} else if (type == 0x0006) { /* Message was received offline. */
-
-			/* XXX not sure if this actually gets sent. */
-			args.icbmflags |= AIM_IMFLAGS_OFFLINE;
-
-		} else if (type == 0x0008) { /* I-HAVE-A-REALLY-PURTY-ICON Flag */
-
-			args.iconlen = aimbs_get32(bs);
-			aimbs_get16(bs); /* 0x0001 */
-			args.iconsum = aimbs_get16(bs);
-			args.iconstamp = aimbs_get32(bs);
-
-			/*
-			 * This looks to be a client bug.  MacAIM 4.3 will
-			 * send this tag, but with all zero values, in the
-			 * first message of a conversation. This makes no
-			 * sense whatsoever, so I'm going to say its a bug.
-			 *
-			 * You really shouldn't advertise a zero-length icon
-			 * anyway.
-			 *
-			 */
-			if (args.iconlen) {
-				args.icbmflags |= AIM_IMFLAGS_HASICON;
-			}
-
-		} else if (type == 0x0009) {
-
-			args.icbmflags |= AIM_IMFLAGS_BUDDYREQ;
-
-		} else if (type == 0x0017) {
-
-			args.extdatalen = length;
-			args.extdata = aimbs_getraw(bs, args.extdatalen);
-
-		} else {
-			// imcb_error(sess->aux_data, "Unknown TLV encountered");
-		}
-
-		/*
-		 * This is here to protect ourselves from ourselves.  That
-		 * is, if something above doesn't completly parse its value
-		 * section, or, worse, overparses it, this will set the
-		 * stream where it needs to be in order to land on the next
-		 * TLV when the loop continues.
-		 *
-		 */
-		aim_bstream_setpos(bs, endpos);
-	}
-
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, channel, userinfo, &args);
-	}
-
-	aim_mpmsg_free(sess, &args.mpmsg);
-	g_free(args.extdata);
-
-	return ret;
-}
-
-
-static void incomingim_ch2_chat_free(aim_session_t *sess, struct aim_incomingim_ch2_args *args)
-{
-
-	/* XXX aim_chat_roominfo_free() */
-	g_free(args->info.chat.roominfo.name);
-
-	return;
-}
-
-static void incomingim_ch2_chat(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac,
-                                aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args, aim_bstream_t *servdata)
-{
-
-	/*
-	 * Chat room info.
-	 */
-	if (servdata) {
-		aim_chat_readroominfo(servdata, &args->info.chat.roominfo);
-	}
-
-	args->destructor = (void *) incomingim_ch2_chat_free;
-
-	return;
-}
-
-static void incomingim_ch2_icqserverrelay_free(aim_session_t *sess, struct aim_incomingim_ch2_args *args)
-{
-
-	g_free((char *) args->info.rtfmsg.rtfmsg);
-
-	return;
-}
-
-/*
- * The relationship between AIM_CAPS_ICQSERVERRELAY and AIM_CAPS_ICQRTF is
- * kind of odd. This sends the client ICQRTF since that is all that I've seen
- * SERVERRELAY used for.
- *
- * Note that this is all little-endian.  Cringe.
- *
- * This cap is used for auto status message replies, too [ft]
- *
- */
-static void incomingim_ch2_icqserverrelay(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac,
-                                          aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args,
-                                          aim_bstream_t *servdata)
-{
-	guint16 hdrlen, msglen, dc;
-	guint8 msgtype;
-	guint8 *plugin;
-	int i = 0, tmp = 0;
-	struct im_connection *ic = sess->aux_data;
-
-	/* at the moment we just can deal with requests, not with cancel or accept */
-	if (args->status != 0) {
-		return;
-	}
-
-	hdrlen = aimbs_getle16(servdata);
-
-	aim_bstream_advance(servdata, 0x02); /* protocol version */
-	plugin = aimbs_getraw(servdata, 0x10); /* following data is a message or
-	                                      something plugin specific */
-	/* as there is no plugin handling, just skip the rest */
-	aim_bstream_advance(servdata, hdrlen - 0x12);
-
-	hdrlen = aimbs_getle16(servdata);
-	dc = aimbs_getle16(servdata); /* save the sequence number */
-	aim_bstream_advance(servdata, hdrlen - 0x02);
-
-	/* TODO is it a message or something for a plugin? */
-	for (i = 0; i < 0x10; i++) {
-		tmp |= plugin[i];
-	}
-
-	if (!tmp) { /* message follows */
-
-		msgtype = aimbs_getle8(servdata);
-		aimbs_getle8(servdata); /* msgflags */
-
-		aim_bstream_advance(servdata, 0x04); /* status code and priority code */
-
-		msglen = aimbs_getle16(servdata); /* message string length */
-		args->info.rtfmsg.rtfmsg = aimbs_getstr(servdata, msglen);
-
-		switch (msgtype) {
-		case AIM_MTYPE_PLAIN:
-
-			args->info.rtfmsg.fgcolor = aimbs_getle32(servdata);
-			args->info.rtfmsg.bgcolor = aimbs_getle32(servdata);
-
-			hdrlen = aimbs_getle32(servdata);
-			aim_bstream_advance(servdata, hdrlen);
-
-			/* XXX This is such a hack. */
-			args->reqclass = AIM_CAPS_ICQRTF;
-			break;
-
-		case AIM_MTYPE_AUTOAWAY:
-		case AIM_MTYPE_AUTOBUSY:
-		case AIM_MTYPE_AUTONA:
-		case AIM_MTYPE_AUTODND:
-		case AIM_MTYPE_AUTOFFC:
-		case 0x9c: /* ICQ 5 seems to send this */
-			aim_send_im_ch2_statusmessage(sess, userinfo->sn, args->cookie,
-			                              ic->away ? ic->away : "", sess->aim_icq_state, dc);
-			break;
-
-		}
-	} /* message or plugin specific */
-
-	g_free(plugin);
-	args->destructor = (void *) incomingim_ch2_icqserverrelay_free;
-
-	return;
-}
-
-typedef void (*ch2_args_destructor_t)(aim_session_t *sess, struct aim_incomingim_ch2_args *args);
-
-static int incomingim_ch2(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, guint16 channel,
-                          aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, guint8 *cookie)
-{
-	aim_rxcallback_t userfunc;
-	aim_tlv_t *block1, *servdatatlv;
-	aim_tlvlist_t *list2;
-	struct aim_incomingim_ch2_args args;
-	aim_bstream_t bbs, sdbs, *sdbsptr = NULL;
-	guint8 *cookie2;
-	int ret = 0;
-
-	char clientip1[30] = { "" };
-	char clientip2[30] = { "" };
-	char verifiedip[30] = { "" };
-
-	memset(&args, 0, sizeof(args));
-
-	/*
-	 * There's another block of TLVs embedded in the type 5 here.
-	 */
-	block1 = aim_gettlv(tlvlist, 0x0005, 1);
-	aim_bstream_init(&bbs, block1->value, block1->length);
-
-	/*
-	 * First two bytes represent the status of the connection.
-	 *
-	 * 0 is a request, 1 is a deny (?), 2 is an accept
-	 */
-	args.status = aimbs_get16(&bbs);
-
-	/*
-	 * Next comes the cookie.  Should match the ICBM cookie.
-	 */
-	cookie2 = aimbs_getraw(&bbs, 8);
-	if (memcmp(cookie, cookie2, 8) != 0) {
-		imcb_error(sess->aux_data, "rend: warning cookies don't match!");
-	}
-	memcpy(args.cookie, cookie2, 8);
-	g_free(cookie2);
-
-	/*
-	 * The next 16bytes are a capability block so we can
-	 * identify what type of rendezvous this is.
-	 */
-	args.reqclass = aim_getcap(sess, &bbs, 0x10);
-
-	/*
-	 * What follows may be TLVs or nothing, depending on the
-	 * purpose of the message.
-	 *
-	 * Ack packets for instance have nothing more to them.
-	 */
-	list2 = aim_readtlvchain(&bbs);
-
-	/*
-	 * IP address from the perspective of the client.
-	 */
-	if (aim_gettlv(list2, 0x0002, 1)) {
-		aim_tlv_t *iptlv;
-
-		iptlv = aim_gettlv(list2, 0x0002, 1);
-
-		g_snprintf(clientip1, sizeof(clientip1), "%d.%d.%d.%d",
-		           aimutil_get8(iptlv->value + 0),
-		           aimutil_get8(iptlv->value + 1),
-		           aimutil_get8(iptlv->value + 2),
-		           aimutil_get8(iptlv->value + 3));
-	}
-
-	/*
-	 * Secondary IP address from the perspective of the client.
-	 */
-	if (aim_gettlv(list2, 0x0003, 1)) {
-		aim_tlv_t *iptlv;
-
-		iptlv = aim_gettlv(list2, 0x0003, 1);
-
-		g_snprintf(clientip2, sizeof(clientip2), "%d.%d.%d.%d",
-		           aimutil_get8(iptlv->value + 0),
-		           aimutil_get8(iptlv->value + 1),
-		           aimutil_get8(iptlv->value + 2),
-		           aimutil_get8(iptlv->value + 3));
-	}
-
-	/*
-	 * Verified IP address (from the perspective of Oscar).
-	 *
-	 * This is added by the server.
-	 */
-	if (aim_gettlv(list2, 0x0004, 1)) {
-		aim_tlv_t *iptlv;
-
-		iptlv = aim_gettlv(list2, 0x0004, 1);
-
-		g_snprintf(verifiedip, sizeof(verifiedip), "%d.%d.%d.%d",
-		           aimutil_get8(iptlv->value + 0),
-		           aimutil_get8(iptlv->value + 1),
-		           aimutil_get8(iptlv->value + 2),
-		           aimutil_get8(iptlv->value + 3));
-	}
-
-	/*
-	 * Port number for something.
-	 */
-	if (aim_gettlv(list2, 0x0005, 1)) {
-		args.port = aim_gettlv16(list2, 0x0005, 1);
-	}
-
-	/*
-	 * Error code.
-	 */
-	if (aim_gettlv(list2, 0x000b, 1)) {
-		args.errorcode = aim_gettlv16(list2, 0x000b, 1);
-	}
-
-	/*
-	 * Invitation message / chat description.
-	 */
-	if (aim_gettlv(list2, 0x000c, 1)) {
-		args.msg = aim_gettlv_str(list2, 0x000c, 1);
-	}
-
-	/*
-	 * Character set.
-	 */
-	if (aim_gettlv(list2, 0x000d, 1)) {
-		args.encoding = aim_gettlv_str(list2, 0x000d, 1);
-	}
-
-	/*
-	 * Language.
-	 */
-	if (aim_gettlv(list2, 0x000e, 1)) {
-		args.language = aim_gettlv_str(list2, 0x000e, 1);
-	}
-
-	/* Unknown -- two bytes = 0x0001 */
-	if (aim_gettlv(list2, 0x000a, 1)) {
-		;
-	}
-
-	/* Unknown -- no value */
-	if (aim_gettlv(list2, 0x000f, 1)) {
-		;
-	}
-
-	if (strlen(clientip1)) {
-		args.clientip = (char *) clientip1;
-	}
-	if (strlen(clientip2)) {
-		args.clientip2 = (char *) clientip2;
-	}
-	if (strlen(verifiedip)) {
-		args.verifiedip = (char *) verifiedip;
-	}
-
-	/*
-	 * This is must be present in PROPOSALs, but will probably not
-	 * exist in CANCELs and ACCEPTs.
-	 *
-	 * Service Data blocks are module-specific in format.
-	 */
-	if ((servdatatlv = aim_gettlv(list2, 0x2711 /* 10001 */, 1))) {
-
-		aim_bstream_init(&sdbs, servdatatlv->value, servdatatlv->length);
-		sdbsptr = &sdbs;
-	}
-
-	if (args.reqclass & AIM_CAPS_ICQSERVERRELAY) {
-		incomingim_ch2_icqserverrelay(sess, mod, rx, snac, userinfo, &args, sdbsptr);
-	} else if (args.reqclass & AIM_CAPS_CHAT) {
-		incomingim_ch2_chat(sess, mod, rx, snac, userinfo, &args, sdbsptr);
-	}
-
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, channel, userinfo, &args);
-	}
-
-
-	if (args.destructor) {
-		((ch2_args_destructor_t) args.destructor)(sess, &args);
-	}
-
-	g_free((char *) args.msg);
-	g_free((char *) args.encoding);
-	g_free((char *) args.language);
-
-	aim_freetlvchain(&list2);
-
-	return ret;
-}
-
-static int incomingim_ch4(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, guint16 channel,
-                          aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, guint8 *cookie)
-{
-	aim_bstream_t meat;
-	aim_rxcallback_t userfunc;
-	aim_tlv_t *block;
-	struct aim_incomingim_ch4_args args;
-	int ret = 0;
-
-	/*
-	 * Make a bstream for the meaty part.  Yum.  Meat.
-	 */
-	if (!(block = aim_gettlv(tlvlist, 0x0005, 1))) {
-		return -1;
-	}
-	aim_bstream_init(&meat, block->value, block->length);
-
-	args.uin = aimbs_getle32(&meat);
-	args.type = aimbs_getle16(&meat);
-	args.msg = (char *) aimbs_getraw(&meat, aimbs_getle16(&meat));
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, channel, userinfo, &args);
-	}
-
-	g_free(args.msg);
-
-	return ret;
-}
-
-/*
- * It can easily be said that parsing ICBMs is THE single
- * most difficult thing to do in the in AIM protocol.  In
- * fact, I think I just did say that.
- *
- * Below is the best damned solution I've come up with
- * over the past sixteen months of battling with it. This
- * can parse both away and normal messages from every client
- * I have access to.  Its not fast, its not clean.  But it works.
- *
- */
-static int incomingim(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int i, ret = 0;
-	guint8 cookie[8];
-	guint16 channel;
-	aim_userinfo_t userinfo;
-
-	memset(&userinfo, 0x00, sizeof(aim_userinfo_t));
-
-	/*
-	 * Read ICBM Cookie.  And throw away.
-	 */
-	for (i = 0; i < 8; i++) {
-		cookie[i] = aimbs_get8(bs);
-	}
-
-	/*
-	 * Channel ID.
-	 *
-	 * Channel 0x0001 is the message channel.  There are
-	 * other channels for things called "rendezvous"
-	 * which represent chat and some of the other new
-	 * features of AIM2/3/3.5.
-	 *
-	 * Channel 0x0002 is the Rendezvous channel, which
-	 * is where Chat Invitiations and various client-client
-	 * connection negotiations come from.
-	 *
-	 * Channel 0x0004 is used for ICQ authorization, or
-	 * possibly any system notice.
-	 *
-	 */
-	channel = aimbs_get16(bs);
-
-	/*
-	 * Extract the standard user info block.
-	 *
-	 * Note that although this contains TLVs that appear contiguous
-	 * with the TLVs read below, they are two different pieces.  The
-	 * userinfo block contains the number of TLVs that contain user
-	 * information, the rest are not even though there is no separation.
-	 * aim_extractuserinfo() returns the number of bytes used by the
-	 * userinfo tlvs, so you can start reading the rest of them right
-	 * afterward.
-	 *
-	 * That also means that TLV types can be duplicated between the
-	 * userinfo block and the rest of the message, however there should
-	 * never be two TLVs of the same type in one block.
-	 *
-	 */
-	aim_extractuserinfo(sess, bs, &userinfo);
-
-	/*
-	 * From here on, its depends on what channel we're on.
-	 *
-	 * Technically all channels have a TLV list have this, however,
-	 * for the common channel 1 case, in-place parsing is used for
-	 * performance reasons (less memory allocation).
-	 */
-	if (channel == 1) {
-
-		ret = incomingim_ch1(sess, mod, rx, snac, channel, &userinfo, bs, cookie);
-
-	} else if (channel == 2) {
-		aim_tlvlist_t *tlvlist;
-
-		/*
-		 * Read block of TLVs (not including the userinfo data).  All
-		 * further data is derived from what is parsed here.
-		 */
-		tlvlist = aim_readtlvchain(bs);
-
-		ret = incomingim_ch2(sess, mod, rx, snac, channel, &userinfo, tlvlist, cookie);
-
-		aim_freetlvchain(&tlvlist);
-
-	} else if (channel == 4) {
-		aim_tlvlist_t *tlvlist;
-
-		tlvlist = aim_readtlvchain(bs);
-		ret = incomingim_ch4(sess, mod, rx, snac, channel, &userinfo, tlvlist, cookie);
-		aim_freetlvchain(&tlvlist);
-
-	} else {
-
-		imcb_error(sess->aux_data, "ICBM received on an unsupported channel.  Ignoring.");
-
-		return 0;
-	}
-
-	return ret;
-}
-
-/*
- * aim_reqicbmparaminfo()
- *
- * Request ICBM parameter information.
- *
- */
-int aim_reqicbmparams(aim_session_t *sess)
-{
-	aim_conn_t *conn;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) {
-		return -EINVAL;
-	}
-
-	return aim_genericreq_n(sess, conn, 0x0004, 0x0004);
-}
-
-/*
- *
- * I definitely recommend sending this.  If you don't, you'll be stuck
- * with the rather unreasonable defaults.  You don't want those.  Send this.
- *
- */
-int aim_seticbmparam(aim_session_t *sess, struct aim_icbmparameters *params)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) {
-		return -EINVAL;
-	}
-
-	if (!params) {
-		return -EINVAL;
-	}
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 16))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, 0x0004, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0004, 0x0002, 0x0000, snacid);
-
-	/* This is read-only (see Parameter Reply). Must be set to zero here. */
-	aimbs_put16(&fr->data, 0x0000);
-
-	/* These are all read-write */
-	aimbs_put32(&fr->data, params->flags);
-	aimbs_put16(&fr->data, params->maxmsglen);
-	aimbs_put16(&fr->data, params->maxsenderwarn);
-	aimbs_put16(&fr->data, params->maxrecverwarn);
-	aimbs_put32(&fr->data, params->minmsginterval);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-static int paraminfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	struct aim_icbmparameters params;
-	aim_rxcallback_t userfunc;
-
-	params.maxchan = aimbs_get16(bs);
-	params.flags = aimbs_get32(bs);
-	params.maxmsglen = aimbs_get16(bs);
-	params.maxsenderwarn = aimbs_get16(bs);
-	params.maxrecverwarn = aimbs_get16(bs);
-	params.minmsginterval = aimbs_get32(bs);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		return userfunc(sess, rx, &params);
-	}
-
-	return 0;
-}
-
-static int missedcall(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	guint16 channel, nummissed, reason;
-	aim_userinfo_t userinfo;
-
-	while (aim_bstream_empty(bs)) {
-
-		channel = aimbs_get16(bs);
-		aim_extractuserinfo(sess, bs, &userinfo);
-		nummissed = aimbs_get16(bs);
-		reason = aimbs_get16(bs);
-
-		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-			ret = userfunc(sess, rx, channel, &userinfo, nummissed, reason);
-		}
-	}
-
-	return ret;
-}
-
-/*
- * Receive the response from an ICQ status message request.  This contains the
- * ICQ status message.  Go figure.
- */
-static int clientautoresp(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac,
-                          aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	guint16 channel, reason;
-	char *sn;
-	guint8 *ck, snlen;
-
-	ck = aimbs_getraw(bs, 8);
-	channel = aimbs_get16(bs);
-	snlen = aimbs_get8(bs);
-	sn = aimbs_getstr(bs, snlen);
-	reason = aimbs_get16(bs);
-
-	switch (reason) {
-	case 0x0003: {         /* ICQ status message.  Maybe other stuff too, you never know with these people. */
-		guint8 statusmsgtype, *msg;
-		guint16 len;
-		guint32 state;
-
-		len = aimbs_getle16(bs);         /* Should be 0x001b */
-		aim_bstream_advance(bs, len);         /* Unknown */
-
-		len = aimbs_getle16(bs);         /* Should be 0x000e */
-		aim_bstream_advance(bs, len);         /* Unknown */
-
-		statusmsgtype = aimbs_getle8(bs);
-		switch (statusmsgtype) {
-		case 0xe8:
-			state = AIM_ICQ_STATE_AWAY;
-			break;
-		case 0xe9:
-			state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_BUSY;
-			break;
-		case 0xea:
-			state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_OUT;
-			break;
-		case 0xeb:
-			state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_DND | AIM_ICQ_STATE_BUSY;
-			break;
-		case 0xec:
-			state = AIM_ICQ_STATE_CHAT;
-			break;
-		default:
-			state = 0;
-			break;
-		}
-
-		aimbs_getle8(bs);         /* Unknown - 0x03 Maybe this means this is an auto-reply */
-		aimbs_getle16(bs);         /* Unknown - 0x0000 */
-		aimbs_getle16(bs);         /* Unknown - 0x0000 */
-
-		len = aimbs_getle16(bs);
-		msg = aimbs_getraw(bs, len);
-
-		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-			ret = userfunc(sess, rx, channel, sn, reason, state, msg);
-		}
-
-		g_free(msg);
-	} break;
-
-	default: {
-		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-			ret = userfunc(sess, rx, channel, sn, reason);
-		}
-	} break;
-	} /* end switch */
-
-	g_free(ck);
-	g_free(sn);
-
-	return ret;
-}
-
-static int msgack(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_rxcallback_t userfunc;
-	guint16 type;
-	guint8 snlen, *ck;
-	char *sn;
-	int ret = 0;
-
-	ck = aimbs_getraw(bs, 8);
-	type = aimbs_get16(bs);
-	snlen = aimbs_get8(bs);
-	sn = aimbs_getstr(bs, snlen);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, type, sn);
-	}
-
-	g_free(sn);
-	g_free(ck);
-
-	return ret;
-}
-
-/*
- * Subtype 0x0014 - Send a mini typing notification (mtn) packet.
- *
- * This is supported by winaim5 and newer, MacAIM bleh and newer, iChat bleh and newer,
- * and Gaim 0.60 and newer.
- *
- */
-int aim_im_sendmtn(aim_session_t *sess, guint16 type1, const char *sn, guint16 type2)
-{
-	aim_conn_t *conn;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0002))) {
-		return -EINVAL;
-	}
-
-	if (!sn) {
-		return -EINVAL;
-	}
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11 + strlen(sn) + 2))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, 0x0004, 0x0014, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0004, 0x0014, 0x0000, snacid);
-
-	/*
-	 * 8 days of light
-	 * Er, that is to say, 8 bytes of 0's
-	 */
-	aimbs_put16(&fr->data, 0x0000);
-	aimbs_put16(&fr->data, 0x0000);
-	aimbs_put16(&fr->data, 0x0000);
-	aimbs_put16(&fr->data, 0x0000);
-
-	/*
-	 * Type 1 (should be 0x0001 for mtn)
-	 */
-	aimbs_put16(&fr->data, type1);
-
-	/*
-	 * Dest sn
-	 */
-	aimbs_put8(&fr->data, strlen(sn));
-	aimbs_putraw(&fr->data, (const guint8 *) sn, strlen(sn));
-
-	/*
-	 * Type 2 (should be 0x0000, 0x0001, or 0x0002 for mtn)
-	 */
-	aimbs_put16(&fr->data, type2);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Subtype 0x0014 - Receive a mini typing notification (mtn) packet.
- *
- * This is supported by winaim5 and newer, MacAIM bleh and newer, iChat bleh and newer,
- * and Gaim 0.60 and newer.
- *
- */
-static int mtn_receive(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	char *sn;
-	guint8 snlen;
-	guint16 type1, type2;
-
-	aim_bstream_advance(bs, 8); /* Unknown - All 0's */
-	type1 = aimbs_get16(bs);
-	snlen = aimbs_get8(bs);
-	sn = aimbs_getstr(bs, snlen);
-	type2 = aimbs_get16(bs);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, type1, sn, type2);
-	}
-
-	g_free(sn);
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0005) {
-		return paraminfo(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == 0x0006) {
-		return outgoingim(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == 0x0007) {
-		return incomingim(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == 0x000a) {
-		return missedcall(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == 0x000b) {
-		return clientautoresp(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == 0x000c) {
-		return msgack(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == 0x0014) {
-		return mtn_receive(sess, mod, rx, snac, bs);
-	}
-
-	return 0;
-}
-
-int msg_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x0004;
-	mod->version = 0x0001;
-	mod->toolid = 0x0110;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "messaging", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
Index: protocols/oscar/im.h
===================================================================
--- protocols/oscar/im.h	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,184 +1,0 @@
-#ifndef __OSCAR_IM_H__
-#define __OSCAR_IM_H__
-
-#define AIM_CB_FAM_MSG 0x0004
-
-/*
- * SNAC Family: Messaging Services.
- */
-#define AIM_CB_MSG_ERROR 0x0001
-#define AIM_CB_MSG_PARAMINFO 0x0005
-#define AIM_CB_MSG_INCOMING 0x0007
-#define AIM_CB_MSG_EVIL 0x0009
-#define AIM_CB_MSG_MISSEDCALL 0x000a
-#define AIM_CB_MSG_CLIENTAUTORESP 0x000b
-#define AIM_CB_MSG_ACK 0x000c
-#define AIM_CB_MSG_MTN 0x0014
-#define AIM_CB_MSG_DEFAULT 0xffff
-
-#define AIM_IMFLAGS_AWAY                0x0001 /* mark as an autoreply */
-#define AIM_IMFLAGS_ACK                 0x0002 /* request a receipt notice */
-#define AIM_IMFLAGS_UNICODE             0x0004
-#define AIM_IMFLAGS_ISO_8859_1          0x0008
-#define AIM_IMFLAGS_BUDDYREQ            0x0010 /* buddy icon requested */
-#define AIM_IMFLAGS_HASICON             0x0020 /* already has icon */
-#define AIM_IMFLAGS_SUBENC_MACINTOSH    0x0040 /* damn that Steve Jobs! */
-#define AIM_IMFLAGS_CUSTOMFEATURES      0x0080 /* features field present */
-#define AIM_IMFLAGS_EXTDATA             0x0100
-#define AIM_IMFLAGS_CUSTOMCHARSET       0x0200 /* charset fields set */
-#define AIM_IMFLAGS_MULTIPART           0x0400 /* ->mpmsg section valid */
-#define AIM_IMFLAGS_OFFLINE             0x0800 /* send to offline user */
-
-/*
- * Multipart message structures.
- */
-typedef struct aim_mpmsg_section_s {
-	guint16 charset;
-	guint16 charsubset;
-	guint8 *data;
-	guint16 datalen;
-	struct aim_mpmsg_section_s *next;
-} aim_mpmsg_section_t;
-
-typedef struct aim_mpmsg_s {
-	int numparts;
-	aim_mpmsg_section_t *parts;
-} aim_mpmsg_t;
-
-int aim_mpmsg_init(aim_session_t *sess, aim_mpmsg_t *mpm);
-void aim_mpmsg_free(aim_session_t *sess, aim_mpmsg_t *mpm);
-
-/*
- * Arguments to aim_send_im_ext().
- *
- * This is really complicated.  But immensely versatile.
- *
- */
-struct aim_sendimext_args {
-
-	/* These are _required_ */
-	const char *destsn;
-	guint32 flags; /* often 0 */
-
-	/* Only required if not using multipart messages */
-	const char *msg;
-	int msglen;
-
-	/* Required if ->msg is not provided */
-	aim_mpmsg_t *mpmsg;
-
-	/* Only used if AIM_IMFLAGS_HASICON is set */
-	guint32 iconlen;
-	time_t iconstamp;
-	guint32 iconsum;
-
-	/* Only used if AIM_IMFLAGS_CUSTOMFEATURES is set */
-	guint8 *features;
-	guint8 featureslen;
-
-	/* Only used if AIM_IMFLAGS_CUSTOMCHARSET is set and mpmsg not used */
-	guint16 charset;
-	guint16 charsubset;
-};
-
-/*
- * This information is provided in the Incoming ICBM callback for
- * Channel 1 ICBM's.
- *
- * Note that although CUSTOMFEATURES and CUSTOMCHARSET say they
- * are optional, both are always set by the current libfaim code.
- * That may or may not change in the future.  It is mainly for
- * consistency with aim_sendimext_args.
- *
- * Multipart messages require some explanation. If you want to use them,
- * I suggest you read all the comments in im.c.
- *
- */
-struct aim_incomingim_ch1_args {
-
-	/* Always provided */
-	aim_mpmsg_t mpmsg;
-	guint32 icbmflags; /* some flags apply only to ->msg, not all mpmsg */
-
-	/* Only provided if message has a human-readable section */
-	char *msg;
-	int msglen;
-
-	/* Only provided if AIM_IMFLAGS_HASICON is set */
-	time_t iconstamp;
-	guint32 iconlen;
-	guint16 iconsum;
-
-	/* Only provided if AIM_IMFLAGS_CUSTOMFEATURES is set */
-	guint8 *features;
-	guint8 featureslen;
-
-	/* Only provided if AIM_IMFLAGS_EXTDATA is set */
-	guint8 extdatalen;
-	guint8 *extdata;
-
-	/* Only used if AIM_IMFLAGS_CUSTOMCHARSET is set */
-	guint16 charset;
-	guint16 charsubset;
-};
-
-/* Valid values for channel 2 args->status */
-#define AIM_RENDEZVOUS_PROPOSE 0x0000
-#define AIM_RENDEZVOUS_CANCEL  0x0001
-#define AIM_RENDEZVOUS_ACCEPT  0x0002
-
-struct aim_incomingim_ch2_args {
-	guint8 cookie[8];
-	guint16 reqclass;
-	guint16 status;
-	guint16 errorcode;
-	const char *clientip;
-	const char *clientip2;
-	const char *verifiedip;
-	guint16 port;
-	const char *msg; /* invite message or file description */
-	const char *encoding;
-	const char *language;
-	union {
-		struct {
-			guint32 checksum;
-			guint32 length;
-			time_t timestamp;
-			guint8 *icon;
-		} icon;
-		struct {
-			struct aim_chat_roominfo roominfo;
-		} chat;
-		struct {
-			guint32 fgcolor;
-			guint32 bgcolor;
-			const char *rtfmsg;
-		} rtfmsg;
-	} info;
-	void *destructor; /* used internally only */
-};
-
-/* Valid values for channel 4 args->type */
-#define AIM_ICQMSG_AUTHREQUEST 0x0006
-#define AIM_ICQMSG_AUTHDENIED 0x0007
-#define AIM_ICQMSG_AUTHGRANTED 0x0008
-
-struct aim_incomingim_ch4_args {
-	guint32 uin; /* Of the sender of the ICBM */
-	guint16 type;
-	char *msg; /* Reason for auth request, deny, or accept */
-};
-
-int aim_send_im_ext(aim_session_t *sess, struct aim_sendimext_args *args);
-int aim_send_im(aim_session_t *, const char *destsn, unsigned short flags, const char *msg);
-int aim_send_typing(aim_session_t *sess, aim_conn_t *conn, int typing);
-int aim_send_im_direct(aim_session_t *, aim_conn_t *, const char *msg, int len);
-const char *aim_directim_getsn(aim_conn_t *conn);
-aim_conn_t *aim_directim_initiate(aim_session_t *, const char *destsn);
-aim_conn_t *aim_directim_connect(aim_session_t *, const char *sn, const char *addr, const guint8 *cookie);
-
-int aim_im_sendmtn(aim_session_t *sess, guint16 type1, const char *sn, guint16 type2);
-int aim_send_im_ch2_statusmessage(aim_session_t *sess, const char *sender, const guint8 *cookie, const char *message,
-                                  const guint8 state, const guint16 dc);
-
-#endif /* __OSCAR_IM_H__ */
Index: protocols/oscar/info.c
===================================================================
--- protocols/oscar/info.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,557 +1,0 @@
-/*
- * aim_info.c
- *
- * The functions here are responsible for requesting and parsing information-
- * gathering SNACs.  Or something like that.
- *
- */
-
-#include <aim.h>
-#include "info.h"
-
-struct aim_priv_inforeq {
-	char sn[MAXSNLEN + 1];
-	guint16 infotype;
-};
-
-int aim_getinfo(aim_session_t *sess, aim_conn_t *conn, const char *sn, guint16 infotype)
-{
-	struct aim_priv_inforeq privdata;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !conn || !sn) {
-		return -EINVAL;
-	}
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 12 + 1 + strlen(sn)))) {
-		return -ENOMEM;
-	}
-
-	strncpy(privdata.sn, sn, sizeof(privdata.sn));
-	privdata.infotype = infotype;
-	snacid = aim_cachesnac(sess, 0x0002, 0x0005, 0x0000, &privdata, sizeof(struct aim_priv_inforeq));
-
-	aim_putsnac(&fr->data, 0x0002, 0x0005, 0x0000, snacid);
-	aimbs_put16(&fr->data, infotype);
-	aimbs_put8(&fr->data, strlen(sn));
-	aimbs_putraw(&fr->data, (guint8 *) sn, strlen(sn));
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Capability blocks.
- *
- * These are CLSIDs. They should actually be of the form:
- *
- * {0x0946134b, 0x4c7f, 0x11d1,
- *  {0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}},
- *
- * But, eh.
- */
-static const struct {
-	guint32 flag;
-	guint8 data[16];
-} aim_caps[] = {
-
-	/*
-	 * Chat is oddball.
-	 */
-	{ AIM_CAPS_CHAT,
-	  { 0x74, 0x8f, 0x24, 0x20, 0x62, 0x87, 0x11, 0xd1,
-	    0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } },
-
-	/*
-	 * These are mostly in order.
-	 */
-	{ AIM_CAPS_VOICE,
-	  { 0x09, 0x46, 0x13, 0x41, 0x4c, 0x7f, 0x11, 0xd1,
-	    0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } },
-
-	{ AIM_CAPS_SENDFILE,
-	  { 0x09, 0x46, 0x13, 0x43, 0x4c, 0x7f, 0x11, 0xd1,
-	    0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } },
-
-	/*
-	 * Advertised by the EveryBuddy client.
-	 */
-	{ AIM_CAPS_ICQ,
-	  { 0x09, 0x46, 0x13, 0x44, 0x4c, 0x7f, 0x11, 0xd1,
-	    0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } },
-
-	{ AIM_CAPS_IMIMAGE,
-	  { 0x09, 0x46, 0x13, 0x45, 0x4c, 0x7f, 0x11, 0xd1,
-	    0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } },
-
-	{ AIM_CAPS_BUDDYICON,
-	  { 0x09, 0x46, 0x13, 0x46, 0x4c, 0x7f, 0x11, 0xd1,
-	    0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } },
-
-	{ AIM_CAPS_SAVESTOCKS,
-	  { 0x09, 0x46, 0x13, 0x47, 0x4c, 0x7f, 0x11, 0xd1,
-	    0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } },
-
-	{ AIM_CAPS_GETFILE,
-	  { 0x09, 0x46, 0x13, 0x48, 0x4c, 0x7f, 0x11, 0xd1,
-	    0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } },
-
-	/*
-	 * Client supports channel 2 extended, TLV(0x2711) based messages.
-	 * Currently used only by ICQ clients. ICQ clients and clones use this GUID
-	 * as message format sign. Trillian client use another GUID in channel 2
-	 * messages to implement its own message format (trillian doesn't use
-	 * TLV(x2711) in SecureIM channel 2 messages!).
-	 */
-	{ AIM_CAPS_ICQSERVERRELAY,
-	  { 0x09, 0x46, 0x13, 0x49, 0x4c, 0x7f, 0x11, 0xd1,
-	    0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } },
-
-	/*
-	 * Indeed, there are two of these.  The former appears to be correct,
-	 * but in some versions of winaim, the second one is set.  Either they
-	 * forgot to fix endianness, or they made a typo. It really doesn't
-	 * matter which.
-	 */
-	{ AIM_CAPS_GAMES,
-	  { 0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1,
-	    0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } },
-	{ AIM_CAPS_GAMES2,
-	  { 0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1,
-	    0x22, 0x82, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } },
-
-	{ AIM_CAPS_SENDBUDDYLIST,
-	  { 0x09, 0x46, 0x13, 0x4b, 0x4c, 0x7f, 0x11, 0xd1,
-	    0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } },
-
-	{ AIM_CAPS_UTF8,
-	  { 0x09, 0x46, 0x13, 0x4E, 0x4C, 0x7F, 0x11, 0xD1,
-	    0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } },
-
-	{ AIM_CAPS_ICQRTF,
-	  { 0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34,
-	    0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x92 } },
-
-	{ AIM_CAPS_ICQUNKNOWN,
-	  { 0x2e, 0x7a, 0x64, 0x75, 0xfa, 0xdf, 0x4d, 0xc8,
-	    0x88, 0x6f, 0xea, 0x35, 0x95, 0xfd, 0xb6, 0xdf } },
-
-	{ AIM_CAPS_EMPTY,
-	  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
-
-	{ AIM_CAPS_TRILLIANCRYPT,
-	  { 0xf2, 0xe7, 0xc7, 0xf4, 0xfe, 0xad, 0x4d, 0xfb,
-	    0xb2, 0x35, 0x36, 0x79, 0x8b, 0xdf, 0x00, 0x00 } },
-
-	{ AIM_CAPS_APINFO,
-	  { 0xAA, 0x4A, 0x32, 0xB5, 0xF8, 0x84, 0x48, 0xc6,
-	    0xA3, 0xD7, 0x8C, 0x50, 0x97, 0x19, 0xFD, 0x5B } },
-
-	{ AIM_CAPS_INTEROP,
-	  { 0x09, 0x46, 0x13, 0x4d, 0x4c, 0x7f, 0x11, 0xd1,
-	    0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } },
-
-	{ AIM_CAPS_ICHAT,
-	  { 0x09, 0x46, 0x00, 0x00, 0x4c, 0x7f, 0x11, 0xd1,
-	    0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 } },
-
-	{ AIM_CAPS_LAST }
-};
-
-/*
- * This still takes a length parameter even with a bstream because capabilities
- * are not naturally bounded.
- *
- */
-guint32 aim_getcap(aim_session_t *sess, aim_bstream_t *bs, int len)
-{
-	guint32 flags = 0;
-	int offset;
-
-	for (offset = 0; aim_bstream_empty(bs) && (offset < len); offset += 0x10) {
-		guint8 *cap;
-		int i, identified;
-
-		cap = aimbs_getraw(bs, 0x10);
-
-		for (i = 0, identified = 0; !(aim_caps[i].flag & AIM_CAPS_LAST); i++) {
-
-			if (memcmp(&aim_caps[i].data, cap, 0x10) == 0) {
-				flags |= aim_caps[i].flag;
-				identified++;
-				break; /* should only match once... */
-
-			}
-		}
-
-		if (!identified) {
-			/*FIXME*/
-			/*REMOVEME :-)
-			g_strdup_printf("unknown capability: {%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
-			                cap[0], cap[1], cap[2], cap[3],
-			                cap[4], cap[5],
-			                cap[6], cap[7],
-			                cap[8], cap[9],
-			                cap[10], cap[11], cap[12], cap[13],
-			                cap[14], cap[15]);
-			*/
-		}
-
-		g_free(cap);
-	}
-
-	return flags;
-}
-
-int aim_putcap(aim_bstream_t *bs, guint32 caps)
-{
-	int i;
-
-	if (!bs) {
-		return -EINVAL;
-	}
-
-	for (i = 0; aim_bstream_empty(bs); i++) {
-
-		if (aim_caps[i].flag == AIM_CAPS_LAST) {
-			break;
-		}
-
-		if (caps & aim_caps[i].flag) {
-			aimbs_putraw(bs, aim_caps[i].data, 0x10);
-		}
-
-	}
-
-	return 0;
-}
-
-/*
- * AIM is fairly regular about providing user info.  This is a generic
- * routine to extract it in its standard form.
- */
-int aim_extractuserinfo(aim_session_t *sess, aim_bstream_t *bs, aim_userinfo_t *outinfo)
-{
-	int curtlv, tlvcnt;
-	guint8 snlen;
-
-	if (!bs || !outinfo) {
-		return -EINVAL;
-	}
-
-	/* Clear out old data first */
-	memset(outinfo, 0x00, sizeof(aim_userinfo_t));
-
-	/*
-	 * Screen name.  Stored as an unterminated string prepended with a
-	 * byte containing its length.
-	 */
-	snlen = aimbs_get8(bs);
-	aimbs_getrawbuf(bs, (guint8 *) outinfo->sn, snlen);
-
-	/*
-	 * Warning Level.  Stored as an unsigned short.
-	 */
-	outinfo->warnlevel = aimbs_get16(bs);
-
-	/*
-	 * TLV Count. Unsigned short representing the number of
-	 * Type-Length-Value triples that follow.
-	 */
-	tlvcnt = aimbs_get16(bs);
-
-	/*
-	 * Parse out the Type-Length-Value triples as they're found.
-	 */
-	for (curtlv = 0; curtlv < tlvcnt; curtlv++) {
-		int endpos;
-		guint16 type, length;
-
-		type = aimbs_get16(bs);
-		length = aimbs_get16(bs);
-
-		endpos = aim_bstream_curpos(bs) + length;
-
-		if (type == 0x0001) {
-			/*
-			 * Type = 0x0001: User flags
-			 *
-			 * Specified as any of the following ORed together:
-			 *      0x0001  Trial (user less than 60days)
-			 *      0x0002  Unknown bit 2
-			 *      0x0004  AOL Main Service user
-			 *      0x0008  Unknown bit 4
-			 *      0x0010  Free (AIM) user
-			 *      0x0020  Away
-			 *      0x0400  ActiveBuddy
-			 *
-			 */
-			outinfo->flags = aimbs_get16(bs);
-			outinfo->present |= AIM_USERINFO_PRESENT_FLAGS;
-
-		} else if (type == 0x0002) {
-			/*
-			 * Type = 0x0002: Member-Since date.
-			 *
-			 * The time/date that the user originally registered for
-			 * the service, stored in time_t format.
-			 */
-			outinfo->membersince = aimbs_get32(bs);
-			outinfo->present |= AIM_USERINFO_PRESENT_MEMBERSINCE;
-
-		} else if (type == 0x0003) {
-			/*
-			 * Type = 0x0003: On-Since date.
-			 *
-			 * The time/date that the user started their current
-			 * session, stored in time_t format.
-			 */
-			outinfo->onlinesince = aimbs_get32(bs);
-			outinfo->present |= AIM_USERINFO_PRESENT_ONLINESINCE;
-
-		} else if (type == 0x0004) {
-			/*
-			 * Type = 0x0004: Idle time.
-			 *
-			 * Number of seconds since the user actively used the
-			 * service.
-			 *
-			 * Note that the client tells the server when to start
-			 * counting idle times, so this may or may not be
-			 * related to reality.
-			 */
-			outinfo->idletime = aimbs_get16(bs);
-			outinfo->present |= AIM_USERINFO_PRESENT_IDLE;
-
-		} else if (type == 0x0006) {
-			/*
-			 * Type = 0x0006: ICQ Online Status
-			 *
-			 * ICQ's Away/DND/etc "enriched" status. Some decoding
-			 * of values done by Scott <darkagl@pcnet.com>
-			 */
-			aimbs_get16(bs);
-			outinfo->icqinfo.status = aimbs_get16(bs);
-			outinfo->present |= AIM_USERINFO_PRESENT_ICQEXTSTATUS;
-
-		} else if (type == 0x000a) {
-			/*
-			 * Type = 0x000a
-			 *
-			 * ICQ User IP Address.
-			 * Ahh, the joy of ICQ security.
-			 */
-			outinfo->icqinfo.ipaddr = aimbs_get32(bs);
-			outinfo->present |= AIM_USERINFO_PRESENT_ICQIPADDR;
-
-		} else if (type == 0x000c) {
-			/*
-			 * Type = 0x000c
-			 *
-			 * random crap containing the IP address,
-			 * apparently a port number, and some Other Stuff.
-			 *
-			 */
-			aimbs_getrawbuf(bs, outinfo->icqinfo.crap, 0x25);
-			outinfo->present |= AIM_USERINFO_PRESENT_ICQDATA;
-
-		} else if (type == 0x000d) {
-			/*
-			 * Type = 0x000d
-			 *
-			 * Capability information.
-			 *
-			 */
-			outinfo->capabilities = aim_getcap(sess, bs, length);
-			outinfo->present |= AIM_USERINFO_PRESENT_CAPABILITIES;
-
-		} else if (type == 0x000e) {
-			/*
-			 * Type = 0x000e
-			 *
-			 * Unknown.  Always of zero length, and always only
-			 * on AOL users.
-			 *
-			 * Ignore.
-			 *
-			 */
-
-		} else if ((type == 0x000f) || (type == 0x0010)) {
-			/*
-			 * Type = 0x000f: Session Length. (AIM)
-			 * Type = 0x0010: Session Length. (AOL)
-			 *
-			 * The duration, in seconds, of the user's current
-			 * session.
-			 *
-			 * Which TLV type this comes in depends on the
-			 * service the user is using (AIM or AOL).
-			 *
-			 */
-			outinfo->sessionlen = aimbs_get32(bs);
-			outinfo->present |= AIM_USERINFO_PRESENT_SESSIONLEN;
-
-		} else {
-
-			/*
-			 * Reaching here indicates that either AOL has
-			 * added yet another TLV for us to deal with,
-			 * or the parsing has gone Terribly Wrong.
-			 *
-			 * Either way, inform the owner and attempt
-			 * recovery.
-			 *
-			 */
-#ifdef DEBUG
-			// imcb_error(sess->aux_data, G_STRLOC);
-#endif
-
-		}
-
-		/* Save ourselves. */
-		aim_bstream_setpos(bs, endpos);
-	}
-
-	return 0;
-}
-
-/*
- * Normally contains:
- *   t(0001)  - short containing max profile length (value = 1024)
- *   t(0002)  - short - unknown (value = 16) [max MIME type length?]
- *   t(0003)  - short - unknown (value = 10)
- *   t(0004)  - short - unknown (value = 2048) [ICQ only?]
- */
-static int rights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_tlvlist_t *tlvlist;
-	aim_rxcallback_t userfunc;
-	int ret = 0;
-	guint16 maxsiglen = 0;
-
-	tlvlist = aim_readtlvchain(bs);
-
-	if (aim_gettlv(tlvlist, 0x0001, 1)) {
-		maxsiglen = aim_gettlv16(tlvlist, 0x0001, 1);
-	}
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, maxsiglen);
-	}
-
-	aim_freetlvchain(&tlvlist);
-
-	return ret;
-}
-
-static int userinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_userinfo_t userinfo;
-	char *text_encoding = NULL, *text = NULL;
-	guint16 text_length = 0;
-	aim_rxcallback_t userfunc;
-	aim_tlvlist_t *tlvlist;
-	aim_tlv_t *tlv;
-	aim_snac_t *origsnac = NULL;
-	struct aim_priv_inforeq *inforeq;
-	int ret = 0;
-
-	origsnac = aim_remsnac(sess, snac->id);
-
-	if (!origsnac || !origsnac->data) {
-		imcb_error(sess->aux_data, "major problem: no snac stored!");
-		return 0;
-	}
-
-	inforeq = (struct aim_priv_inforeq *) origsnac->data;
-
-	if ((inforeq->infotype != AIM_GETINFO_GENERALINFO) &&
-	    (inforeq->infotype != AIM_GETINFO_AWAYMESSAGE) &&
-	    (inforeq->infotype != AIM_GETINFO_CAPABILITIES)) {
-		imcb_error(sess->aux_data, "unknown infotype in request!");
-		return 0;
-	}
-
-	aim_extractuserinfo(sess, bs, &userinfo);
-
-	tlvlist = aim_readtlvchain(bs);
-
-	/*
-	 * Depending on what informational text was requested, different
-	 * TLVs will appear here.
-	 *
-	 * Profile will be 1 and 2, away message will be 3 and 4, caps
-	 * will be 5.
-	 */
-	if (inforeq->infotype == AIM_GETINFO_GENERALINFO) {
-		text_encoding = aim_gettlv_str(tlvlist, 0x0001, 1);
-		if ((tlv = aim_gettlv(tlvlist, 0x0002, 1))) {
-			text = g_new0(char, tlv->length);
-			memcpy(text, tlv->value, tlv->length);
-			text_length = tlv->length;
-		}
-	} else if (inforeq->infotype == AIM_GETINFO_AWAYMESSAGE) {
-		text_encoding = aim_gettlv_str(tlvlist, 0x0003, 1);
-		if ((tlv = aim_gettlv(tlvlist, 0x0004, 1))) {
-			text = g_new0(char, tlv->length);
-			memcpy(text, tlv->value, tlv->length);
-			text_length = tlv->length;
-		}
-	} else if (inforeq->infotype == AIM_GETINFO_CAPABILITIES) {
-		aim_tlv_t *ct;
-
-		if ((ct = aim_gettlv(tlvlist, 0x0005, 1))) {
-			aim_bstream_t cbs;
-
-			aim_bstream_init(&cbs, ct->value, ct->length);
-
-			userinfo.capabilities = aim_getcap(sess, &cbs, ct->length);
-			userinfo.present = AIM_USERINFO_PRESENT_CAPABILITIES;
-		}
-	}
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, &userinfo, inforeq->infotype, text_encoding, text, text_length);
-	}
-
-	g_free(text_encoding);
-	g_free(text);
-
-	aim_freetlvchain(&tlvlist);
-
-	if (origsnac) {
-		g_free(origsnac->data);
-	}
-	g_free(origsnac);
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0003) {
-		return rights(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == 0x0006) {
-		return userinfo(sess, mod, rx, snac, bs);
-	}
-
-	return 0;
-}
-
-int locate_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x0002;
-	mod->version = 0x0001;
-	mod->toolid = 0x0110;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "locate", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
Index: protocols/oscar/info.h
===================================================================
--- protocols/oscar/info.h	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,42 +1,0 @@
-#ifndef __OSCAR_INFO_H__
-#define __OSCAR_INFO_H__
-
-#define AIM_CB_FAM_LOC 0x0002
-
-/*
- * SNAC Family: Location Services.
- */
-#define AIM_CB_LOC_ERROR 0x0001
-#define AIM_CB_LOC_REQRIGHTS 0x0002
-#define AIM_CB_LOC_RIGHTSINFO 0x0003
-#define AIM_CB_LOC_SETUSERINFO 0x0004
-#define AIM_CB_LOC_REQUSERINFO 0x0005
-#define AIM_CB_LOC_USERINFO 0x0006
-#define AIM_CB_LOC_WATCHERSUBREQ 0x0007
-#define AIM_CB_LOC_WATCHERNOT 0x0008
-#define AIM_CB_LOC_DEFAULT 0xffff
-
-#define AIM_CAPS_BUDDYICON      0x00000001
-#define AIM_CAPS_VOICE          0x00000002
-#define AIM_CAPS_IMIMAGE        0x00000004
-#define AIM_CAPS_CHAT           0x00000008
-#define AIM_CAPS_GETFILE        0x00000010
-#define AIM_CAPS_SENDFILE       0x00000020
-#define AIM_CAPS_GAMES          0x00000040
-#define AIM_CAPS_SAVESTOCKS     0x00000080
-#define AIM_CAPS_SENDBUDDYLIST  0x00000100
-#define AIM_CAPS_GAMES2         0x00000200
-#define AIM_CAPS_ICQ            0x00000400
-#define AIM_CAPS_APINFO         0x00000800
-#define AIM_CAPS_ICQRTF         0x00001000
-#define AIM_CAPS_EMPTY          0x00002000
-#define AIM_CAPS_ICQSERVERRELAY 0x00004000
-#define AIM_CAPS_ICQUNKNOWN     0x00008000
-#define AIM_CAPS_TRILLIANCRYPT  0x00010000
-#define AIM_CAPS_UTF8           0x00020000
-#define AIM_CAPS_INTEROP        0x00040000
-#define AIM_CAPS_ICHAT          0x00080000
-#define AIM_CAPS_EXTCHAN2       0x00100000
-#define AIM_CAPS_LAST           0x00200000
-
-#endif /* __OSCAR_INFO_H__ */
Index: protocols/oscar/misc.c
===================================================================
--- protocols/oscar/misc.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,239 +1,0 @@
-
-/*
- * aim_misc.c
- *
- * TODO: Separate a lot of this into an aim_bos.c.
- *
- * Other things...
- *
- *   - Idle setting
- *
- *
- */
-
-#include <aim.h>
-
-/*
- * aim_bos_setprofile(profile)
- *
- * Gives BOS your profile.
- *
- */
-int aim_bos_setprofile(aim_session_t *sess, aim_conn_t *conn, const char *profile, const char *awaymsg, guint32 caps)
-{
-	static const char defencoding[] = { "text/aolrtf; charset=\"utf-8\"" };
-	aim_frame_t *fr;
-	aim_tlvlist_t *tl = NULL;
-	aim_snacid_t snacid;
-
-	/* Build to packet first to get real length */
-	if (profile) {
-		aim_addtlvtochain_raw(&tl, 0x0001, strlen(defencoding), (guint8 *) defencoding);
-		aim_addtlvtochain_raw(&tl, 0x0002, strlen(profile), (guint8 *) profile);
-	}
-
-	/*
-	 * So here's how this works:
-	 *   - You are away when you have a non-zero-length type 4 TLV stored.
-	 *   - You become unaway when you clear the TLV with a zero-length
-	 *       type 4 TLV.
-	 *   - If you do not send the type 4 TLV, your status does not change
-	 *       (that is, if you were away, you'll remain away).
-	 */
-	if (awaymsg) {
-		if (strlen(awaymsg)) {
-			aim_addtlvtochain_raw(&tl, 0x0003, strlen(defencoding), (guint8 *) defencoding);
-			aim_addtlvtochain_raw(&tl, 0x0004, strlen(awaymsg), (guint8 *) awaymsg);
-		} else {
-			aim_addtlvtochain_noval(&tl, 0x0004);
-		}
-	}
-
-	aim_addtlvtochain_caps(&tl, 0x0005, caps);
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + aim_sizetlvchain(&tl)))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, 0x0002, 0x0004, 0x0000, NULL, 0);
-
-	aim_putsnac(&fr->data, 0x0002, 0x004, 0x0000, snacid);
-	aim_writetlvchain(&fr->data, &tl);
-	aim_freetlvchain(&tl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * aim_bos_reqbuddyrights()
- *
- * Request Buddy List rights.
- *
- */
-int aim_bos_reqbuddyrights(aim_session_t *sess, aim_conn_t *conn)
-{
-	return aim_genericreq_n(sess, conn, 0x0003, 0x0002);
-}
-
-/*
- * Generic routine for sending commands.
- *
- *
- * I know I can do this in a smarter way...but I'm not thinking straight
- * right now...
- *
- * I had one big function that handled all three cases, but then it broke
- * and I split it up into three.  But then I fixed it.  I just never went
- * back to the single.  I don't see any advantage to doing it either way.
- *
- */
-int aim_genericreq_n(aim_session_t *sess, aim_conn_t *conn, guint16 family, guint16 subtype)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid = 0x00000000;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10))) {
-		return -ENOMEM;
-	}
-
-	aim_putsnac(&fr->data, family, subtype, 0x0000, snacid);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-int aim_genericreq_n_snacid(aim_session_t *sess, aim_conn_t *conn, guint16 family, guint16 subtype)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, family, subtype, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, family, subtype, 0x0000, snacid);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-int aim_genericreq_l(aim_session_t *sess, aim_conn_t *conn, guint16 family, guint16 subtype, guint32 *longdata)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!longdata) {
-		return aim_genericreq_n(sess, conn, family, subtype);
-	}
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, family, subtype, 0x0000, NULL, 0);
-
-	aim_putsnac(&fr->data, family, subtype, 0x0000, snacid);
-	aimbs_put32(&fr->data, *longdata);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-int aim_genericreq_s(aim_session_t *sess, aim_conn_t *conn, guint16 family, guint16 subtype, guint16 *shortdata)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!shortdata) {
-		return aim_genericreq_n(sess, conn, family, subtype);
-	}
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 2))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, family, subtype, 0x0000, NULL, 0);
-
-	aim_putsnac(&fr->data, family, subtype, 0x0000, snacid);
-	aimbs_put16(&fr->data, *shortdata);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * aim_bos_reqlocaterights()
- *
- * Request Location services rights.
- *
- */
-int aim_bos_reqlocaterights(aim_session_t *sess, aim_conn_t *conn)
-{
-	return aim_genericreq_n(sess, conn, 0x0002, 0x0002);
-}
-
-/*
- * Should be generic enough to handle the errors for all groups.
- *
- */
-static int generror(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	int error = 0;
-	aim_rxcallback_t userfunc;
-	aim_snac_t *snac2;
-
-	snac2 = aim_remsnac(sess, snac->id);
-
-	if (aim_bstream_empty(bs)) {
-		error = aimbs_get16(bs);
-	}
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, error, snac2 ? snac2->data : NULL);
-	}
-
-	if (snac2) {
-		g_free(snac2->data);
-	}
-	g_free(snac2);
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0001) {
-		return generror(sess, mod, rx, snac, bs);
-	} else if ((snac->family == 0xffff) && (snac->subtype == 0xffff)) {
-		aim_rxcallback_t userfunc;
-
-		if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-			return userfunc(sess, rx);
-		}
-	}
-
-	return 0;
-}
-
-int misc_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0xffff;
-	mod->version = 0x0000;
-	mod->flags = AIM_MODFLAG_MULTIFAMILY;
-	strncpy(mod->name, "misc", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
-
-
Index: protocols/oscar/msgcookie.c
===================================================================
--- protocols/oscar/msgcookie.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,172 +1,0 @@
-/*
- * Cookie Caching stuff. Adam wrote this, apparently just some
- * derivatives of n's SNAC work. I cleaned it up, added comments.
- *
- */
-
-/*
- * I'm assuming that cookies are type-specific. that is, we can have
- * "1234578" for type 1 and type 2 concurrently. if i'm wrong, then we
- * lose some error checking. if we assume cookies are not type-specific and are
- * wrong, we get quirky behavior when cookies step on each others' toes.
- */
-
-#include <aim.h>
-#include "info.h"
-
-/**
- * aim_cachecookie - appends a cookie to the cookie list
- * @sess: session to add to
- * @cookie: pointer to struct to append
- *
- * if cookie->cookie for type cookie->type is found, updates the
- * ->addtime of the found structure; otherwise adds the given cookie
- * to the cache
- *
- * returns -1 on error, 0 on append, 1 on update.  the cookie you pass
- * in may be free'd, so don't count on its value after calling this!
- *
- */
-int aim_cachecookie(aim_session_t *sess, aim_msgcookie_t *cookie)
-{
-	aim_msgcookie_t *newcook;
-
-	if (!sess || !cookie) {
-		return -EINVAL;
-	}
-
-	newcook = aim_checkcookie(sess, cookie->cookie, cookie->type);
-
-	if (newcook == cookie) {
-		newcook->addtime = time(NULL);
-		return 1;
-	} else if (newcook) {
-		aim_cookie_free(sess, newcook);
-	}
-
-	cookie->addtime = time(NULL);
-
-	cookie->next = sess->msgcookies;
-	sess->msgcookies = cookie;
-
-	return 0;
-}
-
-/**
- * aim_uncachecookie - grabs a cookie from the cookie cache (removes it from the list)
- * @sess: session to grab cookie from
- * @cookie: cookie string to look for
- * @type: cookie type to look for
- *
- * takes a cookie string and a cookie type and finds the cookie struct associated with that duple, removing it from the cookie list ikn the process.
- *
- * if found, returns the struct; if none found (or on error), returns NULL:
- */
-aim_msgcookie_t *aim_uncachecookie(aim_session_t *sess, guint8 *cookie, int type)
-{
-	aim_msgcookie_t *cur, **prev;
-
-	if (!cookie || !sess->msgcookies) {
-		return NULL;
-	}
-
-	for (prev = &sess->msgcookies; (cur = *prev); ) {
-		if ((cur->type == type) &&
-		    (memcmp(cur->cookie, cookie, 8) == 0)) {
-			*prev = cur->next;
-			return cur;
-		}
-		prev = &cur->next;
-	}
-
-	return NULL;
-}
-
-/**
- * aim_mkcookie - generate an aim_msgcookie_t *struct from a cookie string, a type, and a data pointer.
- * @c: pointer to the cookie string array
- * @type: cookie type to use
- * @data: data to be cached with the cookie
- *
- * returns NULL on error, a pointer to the newly-allocated cookie on
- * success.
- *
- */
-aim_msgcookie_t *aim_mkcookie(guint8 *c, int type, void *data)
-{
-	aim_msgcookie_t *cookie;
-
-	if (!c) {
-		return NULL;
-	}
-
-	if (!(cookie = g_new0(aim_msgcookie_t, 1))) {
-		return NULL;
-	}
-
-	cookie->data = data;
-	cookie->type = type;
-	memcpy(cookie->cookie, c, 8);
-
-	return cookie;
-}
-
-/**
- * aim_checkcookie - check to see if a cookietuple has been cached
- * @sess: session to check for the cookie in
- * @cookie: pointer to the cookie string array
- * @type: type of the cookie to look for
- *
- * this returns a pointer to the cookie struct (still in the list) on
- * success; returns NULL on error/not found
- *
- */
-
-aim_msgcookie_t *aim_checkcookie(aim_session_t *sess, const guint8 *cookie, int type)
-{
-	aim_msgcookie_t *cur;
-
-	for (cur = sess->msgcookies; cur; cur = cur->next) {
-		if ((cur->type == type) &&
-		    (memcmp(cur->cookie, cookie, 8) == 0)) {
-			return cur;
-		}
-	}
-
-	return NULL;
-}
-
-/**
- * aim_cookie_free - free an aim_msgcookie_t struct
- * @sess: session to remove the cookie from
- * @cookiep: the address of a pointer to the cookie struct to remove
- *
- * this function removes the cookie *cookie from the list of cookies
- * in sess, and then frees all memory associated with it. including
- * its data! if you want to use the private data after calling this,
- * make sure you copy it first.
- *
- * returns -1 on error, 0 on success.
- *
- */
-int aim_cookie_free(aim_session_t *sess, aim_msgcookie_t *cookie)
-{
-	aim_msgcookie_t *cur, **prev;
-
-	if (!sess || !cookie) {
-		return -EINVAL;
-	}
-
-	for (prev = &sess->msgcookies; (cur = *prev); ) {
-		if (cur == cookie) {
-			*prev = cur->next;
-		} else {
-			prev = &cur->next;
-		}
-	}
-
-	g_free(cookie->data);
-	g_free(cookie);
-
-	return 0;
-}
Index: protocols/oscar/oscar.c
===================================================================
--- protocols/oscar/oscar.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,2720 +1,0 @@
-/*
- * gaim
- *
- * Some code copyright (C) 2002-2006, Jelmer Vernooij <jelmer@samba.org>
- *                                    and the BitlBee team.
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#include <errno.h>
-#include <ctype.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-#include <sys/stat.h>
-#include <glib.h>
-#include "nogaim.h"
-#include "bitlbee.h"
-#include "proxy.h"
-#include "sock.h"
-
-#include "aim.h"
-#include "icq.h"
-#include "bos.h"
-#include "ssi.h"
-#include "im.h"
-#include "info.h"
-#include "buddylist.h"
-#include "chat.h"
-#include "chatnav.h"
-
-/* constants to identify proto_opts */
-#define USEROPT_AUTH      0
-#define USEROPT_AUTHPORT  1
-
-#define UC_AOL          0x02
-#define UC_ADMIN        0x04
-#define UC_UNCONFIRMED  0x08
-#define UC_NORMAL       0x10
-#define UC_AB           0x20
-#define UC_WIRELESS     0x40
-
-#define AIMHASHDATA "http://gaim.sourceforge.net/aim_data.php3"
-
-#define OSCAR_GROUP "Friends"
-
-#define BUF_LEN 2048
-#define BUF_LONG (BUF_LEN * 2)
-
-/* Don't know if support for UTF8 is really working. For now it's UTF16 here.
-   static int gaim_caps = AIM_CAPS_UTF8; */
-
-static int gaim_caps = AIM_CAPS_INTEROP | AIM_CAPS_ICHAT | AIM_CAPS_ICQSERVERRELAY | AIM_CAPS_CHAT;
-static guint8 gaim_features[] = { 0x01, 0x01, 0x01, 0x02 };
-
-struct oscar_data {
-	aim_session_t *sess;
-	aim_conn_t *conn;
-
-	guint cnpa;
-	guint paspa;
-
-	GSList *create_rooms;
-
-	gboolean conf;
-	gboolean reqemail;
-	gboolean setemail;
-	char *email;
-	gboolean setnick;
-	char *newsn;
-	gboolean chpass;
-	char *oldp;
-	char *newp;
-
-	GSList *oscar_chats;
-
-	gboolean killme, no_reconnect;
-	gboolean icq;
-	GSList *evilhack;
-
-	GHashTable *ips;
-
-	struct {
-		guint maxbuddies; /* max users you can watch */
-		guint maxwatchers; /* max users who can watch you */
-		guint maxpermits; /* max users on permit list */
-		guint maxdenies; /* max users on deny list */
-		guint maxsiglen; /* max size (bytes) of profile */
-		guint maxawaymsglen; /* max size (bytes) of posted away message */
-	} rights;
-};
-
-struct create_room {
-	char *name;
-	int exchange;
-};
-
-struct chat_connection {
-	char *name;
-	char *show; /* AOL did something funny to us */
-	guint16 exchange;
-	guint16 instance;
-	int fd; /* this is redundant since we have the conn below */
-	aim_conn_t *conn;
-	int inpa;
-	int id;
-	struct im_connection *ic; /* i hate this. */
-	struct groupchat *cnv; /* bah. */
-	int maxlen;
-	int maxvis;
-};
-
-struct ask_direct {
-	struct im_connection *ic;
-	char *sn;
-	char ip[64];
-	guint8 cookie[8];
-};
-
-struct icq_auth {
-	struct im_connection *ic;
-	guint32 uin;
-};
-
-static char *extract_name(const char *name)
-{
-	char *tmp;
-	int i, j;
-	char *x = strchr(name, '-');
-
-	if (!x) {
-		return g_strdup(name);
-	}
-	x = strchr(++x, '-');
-	if (!x) {
-		return g_strdup(name);
-	}
-	tmp = g_strdup(++x);
-
-	for (i = 0, j = 0; x[i]; i++) {
-		char hex[3];
-		if (x[i] != '%') {
-			tmp[j++] = x[i];
-			continue;
-		}
-		strncpy(hex, x + ++i, 2); hex[2] = 0;
-		i++;
-		tmp[j++] = (char) strtol(hex, NULL, 16);
-	}
-
-	tmp[j] = 0;
-	return tmp;
-}
-
-static struct chat_connection *find_oscar_chat_by_conn(struct im_connection *ic,
-                                                       aim_conn_t *conn)
-{
-	GSList *g = ((struct oscar_data *) ic->proto_data)->oscar_chats;
-	struct chat_connection *c = NULL;
-
-	while (g) {
-		c = (struct chat_connection *) g->data;
-		if (c->conn == conn) {
-			break;
-		}
-		g = g->next;
-		c = NULL;
-	}
-
-	return c;
-}
-
-static int gaim_parse_auth_resp(aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_login(aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_logout(aim_session_t *, aim_frame_t *, ...);
-static int gaim_handle_redirect(aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_oncoming(aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_offgoing(aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_incoming_im(aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_misses(aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_motd(aim_session_t *, aim_frame_t *, ...);
-static int gaim_chatnav_info(aim_session_t *, aim_frame_t *, ...);
-static int gaim_chat_join(aim_session_t *, aim_frame_t *, ...);
-static int gaim_chat_leave(aim_session_t *, aim_frame_t *, ...);
-static int gaim_chat_info_update(aim_session_t *, aim_frame_t *, ...);
-static int gaim_chat_incoming_msg(aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_ratechange(aim_session_t *, aim_frame_t *, ...);
-static int gaim_bosrights(aim_session_t *, aim_frame_t *, ...);
-static int conninitdone_bos(aim_session_t *, aim_frame_t *, ...);
-static int conninitdone_admin(aim_session_t *, aim_frame_t *, ...);
-static int conninitdone_chat(aim_session_t *, aim_frame_t *, ...);
-static int conninitdone_chatnav(aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_msgerr(aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_locaterights(aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_buddyrights(aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_locerr(aim_session_t *, aim_frame_t *, ...);
-static int gaim_icbm_param_info(aim_session_t *, aim_frame_t *, ...);
-static int gaim_parse_genericerr(aim_session_t *, aim_frame_t *, ...);
-static int gaim_selfinfo(aim_session_t *, aim_frame_t *, ...);
-static int gaim_offlinemsg(aim_session_t *, aim_frame_t *, ...);
-static int gaim_offlinemsgdone(aim_session_t *, aim_frame_t *, ...);
-static int gaim_ssi_parserights(aim_session_t *, aim_frame_t *, ...);
-static int gaim_ssi_parselist(aim_session_t *, aim_frame_t *, ...);
-static int gaim_ssi_parseack(aim_session_t *, aim_frame_t *, ...);
-static int gaim_parsemtn(aim_session_t *, aim_frame_t *, ...);
-static int gaim_icqinfo(aim_session_t *, aim_frame_t *, ...);
-static int gaim_parseaiminfo(aim_session_t *, aim_frame_t *, ...);
-
-static char *msgerrreason[] = {
-	"Invalid error",
-	"Invalid SNAC",
-	"Rate to host",
-	"Rate to client",
-	"Not logged in",
-	"Service unavailable",
-	"Service not defined",
-	"Obsolete SNAC",
-	"Not supported by host",
-	"Not supported by client",
-	"Refused by client",
-	"Reply too big",
-	"Responses lost",
-	"Request denied",
-	"Busted SNAC payload",
-	"Insufficient rights",
-	"In local permit/deny",
-	"Too evil (sender)",
-	"Too evil (receiver)",
-	"User temporarily unavailable",
-	"No match",
-	"List overflow",
-	"Request ambiguous",
-	"Queue full",
-	"Not while on AOL"
-};
-static int msgerrreasonlen = 25;
-
-/* Hurray, this function is NOT thread-safe \o/ */
-static char *normalize(const char *s)
-{
-	static char buf[BUF_LEN];
-	char *t, *u;
-	int x = 0;
-
-	g_return_val_if_fail((s != NULL), NULL);
-
-	u = t = g_ascii_strdown(s, -1);
-
-	while (*t && (x < BUF_LEN - 1)) {
-		if (*t != ' ' && *t != '!') {
-			buf[x] = *t;
-			x++;
-		}
-		t++;
-	}
-	buf[x] = '\0';
-	g_free(u);
-	return buf;
-}
-
-static gboolean oscar_callback(gpointer data, gint source,
-                               b_input_condition condition)
-{
-	aim_conn_t *conn = (aim_conn_t *) data;
-	aim_session_t *sess = aim_conn_getsess(conn);
-	struct im_connection *ic = sess ? sess->aux_data : NULL;
-	struct oscar_data *odata;
-
-	if (!ic) {
-		/* ic is null. we return, else we seg SIGSEG on next line. */
-		return FALSE;
-	}
-
-	if (!g_slist_find(get_connections(), ic)) {
-		/* oh boy. this is probably bad. i guess the only thing we
-		 * can really do is return? */
-		return FALSE;
-	}
-
-	odata = (struct oscar_data *) ic->proto_data;
-
-	if (condition & B_EV_IO_READ) {
-		if (aim_get_command(odata->sess, conn) >= 0) {
-			aim_rxdispatch(odata->sess);
-			if (odata->killme) {
-				imc_logout(ic, !odata->no_reconnect);
-			}
-		} else {
-			if ((conn->type == AIM_CONN_TYPE_BOS) ||
-			    !(aim_getconn_type(odata->sess, AIM_CONN_TYPE_BOS))) {
-				imcb_error(ic, _("Disconnected."));
-				imc_logout(ic, TRUE);
-			} else if (conn->type == AIM_CONN_TYPE_CHAT) {
-				struct chat_connection *c = find_oscar_chat_by_conn(ic, conn);
-				c->conn = NULL;
-				if (c->inpa > 0) {
-					b_event_remove(c->inpa);
-				}
-				c->inpa = 0;
-				c->fd = -1;
-				aim_conn_kill(odata->sess, &conn);
-				imcb_error(sess->aux_data, _("You have been disconnected from chat room %s."), c->name);
-			} else if (conn->type == AIM_CONN_TYPE_CHATNAV) {
-				if (odata->cnpa > 0) {
-					b_event_remove(odata->cnpa);
-				}
-				odata->cnpa = 0;
-				while (odata->create_rooms) {
-					struct create_room *cr = odata->create_rooms->data;
-					g_free(cr->name);
-					odata->create_rooms =
-					        g_slist_remove(odata->create_rooms, cr);
-					g_free(cr);
-					imcb_error(sess->aux_data, _("Chat is currently unavailable"));
-				}
-				aim_conn_kill(odata->sess, &conn);
-			} else if (conn->type == AIM_CONN_TYPE_AUTH) {
-				if (odata->paspa > 0) {
-					b_event_remove(odata->paspa);
-				}
-				odata->paspa = 0;
-				aim_conn_kill(odata->sess, &conn);
-			} else {
-				aim_conn_kill(odata->sess, &conn);
-			}
-		}
-	} else {
-		/* WTF??? */
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-static gboolean oscar_login_connect(gpointer data, gint source, b_input_condition cond)
-{
-	struct im_connection *ic = data;
-	struct oscar_data *odata;
-	aim_session_t *sess;
-	aim_conn_t *conn;
-
-	if (!g_slist_find(get_connections(), ic)) {
-		closesocket(source);
-		return FALSE;
-	}
-
-	odata = ic->proto_data;
-	sess = odata->sess;
-	conn = aim_getconn_type_all(sess, AIM_CONN_TYPE_AUTH);
-
-	if (source < 0) {
-		imcb_error(ic, _("Couldn't connect to host"));
-		imc_logout(ic, TRUE);
-		return FALSE;
-	}
-
-	aim_conn_completeconnect(sess, conn);
-	ic->inpa = b_input_add(conn->fd, B_EV_IO_READ,
-	                       oscar_callback, conn);
-
-	return FALSE;
-}
-
-static void oscar_init(account_t *acc)
-{
-	set_t *s;
-	gboolean icq = g_ascii_isdigit(acc->user[0]);
-
-	if (icq) {
-		set_add(&acc->set, "ignore_auth_requests", "false", set_eval_bool, acc);
-	}
-
-	s = set_add(&acc->set, "server",
-	            icq ? AIM_DEFAULT_LOGIN_SERVER_ICQ
-		    : AIM_DEFAULT_LOGIN_SERVER_AIM, set_eval_account, acc);
-	s->flags |= SET_NOSAVE | ACC_SET_OFFLINE_ONLY;
-
-	if (icq) {
-		s = set_add(&acc->set, "web_aware", "false", set_eval_bool, acc);
-		s->flags |= ACC_SET_OFFLINE_ONLY;
-	}
-
-	acc->flags |= ACC_FLAG_AWAY_MESSAGE;
-}
-
-static void oscar_login(account_t *acc)
-{
-	aim_session_t *sess;
-	aim_conn_t *conn;
-	struct im_connection *ic = imcb_new(acc);
-	struct oscar_data *odata = ic->proto_data = g_new0(struct oscar_data, 1);
-
-	if (g_ascii_isdigit(acc->user[0])) {
-		odata->icq = TRUE;
-	} else {
-		ic->flags |= OPT_DOES_HTML;
-	}
-
-	sess = g_new0(aim_session_t, 1);
-
-	aim_session_init(sess, AIM_SESS_FLAGS_NONBLOCKCONNECT, 0);
-
-	/* we need an immediate queue because we don't use a while-loop to
-	 * see if things need to be sent. */
-	aim_tx_setenqueue(sess, AIM_TX_IMMEDIATE, NULL);
-	odata->sess = sess;
-	sess->aux_data = ic;
-
-	conn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, NULL);
-	if (conn == NULL) {
-		imcb_error(ic, _("Unable to login to AIM"));
-		imc_logout(ic, TRUE);
-		return;
-	}
-
-	imcb_log(ic, _("Signon: %s"), ic->acc->user);
-
-	aim_conn_addhandler(sess, conn, 0x0017, 0x0007, gaim_parse_login, 0);
-	aim_conn_addhandler(sess, conn, 0x0017, 0x0003, gaim_parse_auth_resp, 0);
-
-	conn->status |= AIM_CONN_STATUS_INPROGRESS;
-	conn->fd = proxy_connect(set_getstr(&acc->set, "server"),
-	                         AIM_LOGIN_PORT, oscar_login_connect, ic);
-	if (conn->fd < 0) {
-		imcb_error(ic, _("Couldn't connect to host"));
-		imc_logout(ic, TRUE);
-		return;
-	}
-	aim_request_login(sess, conn, ic->acc->user);
-}
-
-static void oscar_logout(struct im_connection *ic)
-{
-	struct oscar_data *odata = (struct oscar_data *) ic->proto_data;
-
-	while (odata->oscar_chats) {
-		struct chat_connection *n = odata->oscar_chats->data;
-		if (n->inpa > 0) {
-			b_event_remove(n->inpa);
-		}
-		n->inpa = 0;
-		g_free(n->name);
-		g_free(n->show);
-		odata->oscar_chats = g_slist_remove(odata->oscar_chats, n);
-		g_free(n);
-	}
-	while (odata->create_rooms) {
-		struct create_room *cr = odata->create_rooms->data;
-		g_free(cr->name);
-		odata->create_rooms = g_slist_remove(odata->create_rooms, cr);
-		g_free(cr);
-	}
-	if (odata->ips) {
-		g_hash_table_destroy(odata->ips);
-	}
-	if (odata->email) {
-		g_free(odata->email);
-	}
-	if (odata->newp) {
-		g_free(odata->newp);
-	}
-	if (odata->oldp) {
-		g_free(odata->oldp);
-	}
-	if (ic->inpa > 0) {
-		b_event_remove(ic->inpa);
-		ic->inpa = 0;
-	}
-	if (odata->cnpa > 0) {
-		b_event_remove(odata->cnpa);
-		odata->cnpa = 0;
-	}
-	if (odata->paspa > 0) {
-		b_event_remove(odata->paspa);
-		odata->paspa = 0;
-	}
-	aim_session_kill(odata->sess);
-	g_free(odata->sess);
-	odata->sess = NULL;
-	g_free(ic->proto_data);
-	ic->proto_data = NULL;
-}
-
-static gboolean oscar_bos_connect(gpointer data, gint source, b_input_condition cond)
-{
-	struct im_connection *ic = data;
-	struct oscar_data *odata;
-	aim_session_t *sess;
-	aim_conn_t *bosconn;
-
-	if (!g_slist_find(get_connections(), ic)) {
-		closesocket(source);
-		return FALSE;
-	}
-
-	odata = ic->proto_data;
-	sess = odata->sess;
-	bosconn = odata->conn;
-
-	if (source < 0) {
-		imcb_error(ic, _("Could Not Connect"));
-		imc_logout(ic, TRUE);
-		return FALSE;
-	}
-
-	aim_conn_completeconnect(sess, bosconn);
-	ic->inpa = b_input_add(bosconn->fd, B_EV_IO_READ,
-	                       oscar_callback, bosconn);
-	imcb_log(ic, _("Connection established, cookie sent"));
-
-	return FALSE;
-}
-
-static int gaim_parse_auth_resp(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	va_list ap;
-	struct aim_authresp_info *info;
-	int i; char *host; int port;
-	aim_conn_t *bosconn;
-
-	struct im_connection *ic = sess->aux_data;
-	struct oscar_data *od = ic->proto_data;
-
-	port = AIM_LOGIN_PORT;
-
-	va_start(ap, fr);
-	info = va_arg(ap, struct aim_authresp_info *);
-	va_end(ap);
-
-	if (info->errorcode || !info->bosip || !info->cookie) {
-		switch (info->errorcode) {
-		case 0x05:
-			/* Incorrect nick/password */
-			imcb_error(ic, _("Incorrect nickname or password."));
-			{
-				int max = od->icq ? 8 : 16;
-				if (strlen(ic->acc->pass) > max) {
-					imcb_log(ic, "Note that the maximum password "
-					         "length supported by this protocol is "
-					         "%d characters, try logging in using "
-					         "a shorter password.", max);
-				}
-			}
-//			plugin_event(event_error, (void *)980, 0, 0, 0);
-			break;
-		case 0x11:
-			/* Suspended account */
-			imcb_error(ic, _("Your account is currently suspended."));
-			break;
-		case 0x18:
-			/* connecting too frequently */
-			od->no_reconnect = TRUE;
-			imcb_error(ic,
-			           _(
-			                   "You have been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer."));
-			break;
-		case 0x1c:
-			/* client too old */
-			imcb_error(ic, _("The client version you are using is too old. Please upgrade at " WEBSITE));
-			break;
-		default:
-			imcb_error(ic, _("Authentication Failed"));
-			break;
-		}
-		od->killme = TRUE;
-		return 1;
-	}
-
-
-	aim_conn_kill(sess, &fr->conn);
-
-	bosconn = aim_newconn(sess, AIM_CONN_TYPE_BOS, NULL);
-	if (bosconn == NULL) {
-		imcb_error(ic, _("Internal Error"));
-		od->killme = TRUE;
-		return 0;
-	}
-
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_bos, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BOS, AIM_CB_BOS_RIGHTS, gaim_bosrights, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ACK, AIM_CB_ACK_ACK, NULL, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_REDIRECT, gaim_handle_redirect, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_RIGHTSINFO, gaim_parse_locaterights, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, gaim_parse_buddyrights, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, gaim_parse_oncoming, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, gaim_parse_offgoing, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, gaim_parse_incoming_im, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_ERROR, gaim_parse_locerr, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, gaim_parse_misses, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATECHANGE, gaim_parse_ratechange, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, gaim_parse_msgerr, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, gaim_parse_motd, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_PARAMINFO, gaim_icbm_param_info, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_ERROR, gaim_parse_genericerr, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ERROR, gaim_parse_genericerr, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BOS, AIM_CB_BOS_ERROR, gaim_parse_genericerr, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SELFINFO, gaim_selfinfo, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSG, gaim_offlinemsg, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_OFFLINEMSGCOMPLETE, gaim_offlinemsgdone, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_ICQ, AIM_CB_ICQ_INFO, gaim_icqinfo, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_RIGHTSINFO, gaim_ssi_parserights, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_LIST, gaim_ssi_parselist, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SSI, AIM_CB_SSI_SRVACK, gaim_ssi_parseack, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO, gaim_parseaiminfo, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MTN, gaim_parsemtn, 0);
-	aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, gaim_parse_logout, 0);
-
-	((struct oscar_data *) ic->proto_data)->conn = bosconn;
-	for (i = 0; i < (int) strlen(info->bosip); i++) {
-		if (info->bosip[i] == ':') {
-			port = atoi(&(info->bosip[i + 1]));
-			break;
-		}
-	}
-	host = g_strndup(info->bosip, i);
-	bosconn->status |= AIM_CONN_STATUS_INPROGRESS;
-	bosconn->fd = proxy_connect(host, port, oscar_bos_connect, ic);
-	g_free(host);
-	if (bosconn->fd < 0) {
-		imcb_error(ic, _("Could Not Connect"));
-		od->killme = TRUE;
-		return 0;
-	}
-	aim_sendcookie(sess, bosconn, info->cookie);
-	b_event_remove(ic->inpa);
-	ic->inpa = 0;
-
-	return 1;
-}
-
-/* size of icbmui.ocm, the largest module in AIM 3.5 */
-#define AIM_MAX_FILE_SIZE 98304
-
-static int gaim_parse_login(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-#if 0
-	struct client_info_s info = { "gaim", 4, 1, 2010, "us", "en", 0x0004, 0x0000, 0x04b };
-#else
-	struct client_info_s info = AIM_CLIENTINFO_KNOWNGOOD;
-#endif
-	char *key;
-	va_list ap;
-	struct im_connection *ic = sess->aux_data;
-
-	va_start(ap, fr);
-	key = va_arg(ap, char *);
-	va_end(ap);
-
-	aim_send_login(sess, fr->conn, ic->acc->user, ic->acc->pass, &info, key);
-
-	return 1;
-}
-
-static int gaim_parse_logout(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	struct im_connection *ic = sess->aux_data;
-	struct oscar_data *odata = ic->proto_data;
-	int code;
-	va_list ap;
-
-	va_start(ap, fr);
-	code = va_arg(ap, int);
-	va_end(ap);
-
-	imcb_error(ic, "Connection aborted by server: %s", code == 1 ?
-	           "someone else logged in with your account" :
-	           "unknown reason");
-
-	/* Tell BitlBee to disable auto_reconnect if code == 1, since that
-	   means a concurrent login somewhere else. */
-	odata->no_reconnect = code == 1;
-
-	/* DO NOT log out here! Just tell the callback to do it. */
-	odata->killme = TRUE;
-
-	return 1;
-}
-
-static int conninitdone_chat(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	struct im_connection *ic = sess->aux_data;
-	struct chat_connection *chatcon;
-	struct groupchat *c = NULL;
-	static int id = 1;
-
-	aim_conn_addhandler(sess, fr->conn, 0x000e, 0x0001, gaim_parse_genericerr, 0);
-	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERJOIN, gaim_chat_join, 0);
-	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_USERLEAVE, gaim_chat_leave, 0);
-	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_ROOMINFOUPDATE, gaim_chat_info_update, 0);
-	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CHT, AIM_CB_CHT_INCOMINGMSG, gaim_chat_incoming_msg, 0);
-
-	aim_clientready(sess, fr->conn);
-
-	chatcon = find_oscar_chat_by_conn(ic, fr->conn);
-	chatcon->id = id;
-
-	c = bee_chat_by_title(ic->bee, ic, chatcon->show);
-	if (c && !c->data) {
-		chatcon->cnv = c;
-	} else {
-		chatcon->cnv = imcb_chat_new(ic, chatcon->show);
-	}
-	chatcon->cnv->data = chatcon;
-
-	return 1;
-}
-
-static int conninitdone_chatnav(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-
-	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CTN, AIM_CB_CTN_ERROR, gaim_parse_genericerr, 0);
-	aim_conn_addhandler(sess, fr->conn, AIM_CB_FAM_CTN, AIM_CB_CTN_INFO, gaim_chatnav_info, 0);
-
-	aim_clientready(sess, fr->conn);
-
-	aim_chatnav_reqrights(sess, fr->conn);
-
-	return 1;
-}
-
-static gboolean oscar_chatnav_connect(gpointer data, gint source, b_input_condition cond)
-{
-	struct im_connection *ic = data;
-	struct oscar_data *odata;
-	aim_session_t *sess;
-	aim_conn_t *tstconn;
-
-	if (!g_slist_find(get_connections(), ic)) {
-		closesocket(source);
-		return FALSE;
-	}
-
-	odata = ic->proto_data;
-	sess = odata->sess;
-	tstconn = aim_getconn_type_all(sess, AIM_CONN_TYPE_CHATNAV);
-
-	if (source < 0) {
-		aim_conn_kill(sess, &tstconn);
-		return FALSE;
-	}
-
-	aim_conn_completeconnect(sess, tstconn);
-	odata->cnpa = b_input_add(tstconn->fd, B_EV_IO_READ,
-	                          oscar_callback, tstconn);
-
-	return FALSE;
-}
-
-static gboolean oscar_auth_connect(gpointer data, gint source, b_input_condition cond)
-{
-	struct im_connection *ic = data;
-	struct oscar_data *odata;
-	aim_session_t *sess;
-	aim_conn_t *tstconn;
-
-	if (!g_slist_find(get_connections(), ic)) {
-		closesocket(source);
-		return FALSE;
-	}
-
-	odata = ic->proto_data;
-	sess = odata->sess;
-	tstconn = aim_getconn_type_all(sess, AIM_CONN_TYPE_AUTH);
-
-	if (source < 0) {
-		aim_conn_kill(sess, &tstconn);
-		return FALSE;
-	}
-
-	aim_conn_completeconnect(sess, tstconn);
-	odata->paspa = b_input_add(tstconn->fd, B_EV_IO_READ,
-	                           oscar_callback, tstconn);
-
-	return FALSE;
-}
-
-static gboolean oscar_chat_connect(gpointer data, gint source, b_input_condition cond)
-{
-	struct chat_connection *ccon = data;
-	struct im_connection *ic = ccon->ic;
-	struct oscar_data *odata;
-	aim_session_t *sess;
-	aim_conn_t *tstconn;
-
-	if (!g_slist_find(get_connections(), ic)) {
-		closesocket(source);
-		g_free(ccon->show);
-		g_free(ccon->name);
-		g_free(ccon);
-		return FALSE;
-	}
-
-	odata = ic->proto_data;
-	sess = odata->sess;
-	tstconn = ccon->conn;
-
-	if (source < 0) {
-		aim_conn_kill(sess, &tstconn);
-		g_free(ccon->show);
-		g_free(ccon->name);
-		g_free(ccon);
-		return FALSE;
-	}
-
-	aim_conn_completeconnect(sess, ccon->conn);
-	ccon->inpa = b_input_add(tstconn->fd,
-	                         B_EV_IO_READ,
-	                         oscar_callback, tstconn);
-	odata->oscar_chats = g_slist_append(odata->oscar_chats, ccon);
-
-	return FALSE;
-}
-
-/* Hrmph. I don't know how to make this look better. --mid */
-static int gaim_handle_redirect(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	va_list ap;
-	struct aim_redirect_data *redir;
-	struct im_connection *ic = sess->aux_data;
-	aim_conn_t *tstconn;
-	int i;
-	char *host;
-	int port;
-
-	va_start(ap, fr);
-	redir = va_arg(ap, struct aim_redirect_data *);
-	va_end(ap);
-
-	port = AIM_LOGIN_PORT;
-	for (i = 0; i < (int) strlen(redir->ip); i++) {
-		if (redir->ip[i] == ':') {
-			port = atoi(&(redir->ip[i + 1]));
-			break;
-		}
-	}
-	host = g_strndup(redir->ip, i);
-
-	switch (redir->group) {
-	case 0x7: /* Authorizer */
-		tstconn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, NULL);
-		if (tstconn == NULL) {
-			g_free(host);
-			return 1;
-		}
-		aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_admin,
-		                    0);
-//		aim_conn_addhandler(sess, tstconn, 0x0007, 0x0003, gaim_info_change, 0);
-//		aim_conn_addhandler(sess, tstconn, 0x0007, 0x0005, gaim_info_change, 0);
-//		aim_conn_addhandler(sess, tstconn, 0x0007, 0x0007, gaim_account_confirm, 0);
-
-		tstconn->status |= AIM_CONN_STATUS_INPROGRESS;
-		tstconn->fd = proxy_connect(host, port, oscar_auth_connect, ic);
-		if (tstconn->fd < 0) {
-			aim_conn_kill(sess, &tstconn);
-			g_free(host);
-			return 1;
-		}
-		aim_sendcookie(sess, tstconn, redir->cookie);
-		break;
-	case 0xd: /* ChatNav */
-		tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHATNAV, NULL);
-		if (tstconn == NULL) {
-			g_free(host);
-			return 1;
-		}
-		aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE,
-		                    conninitdone_chatnav, 0);
-
-		tstconn->status |= AIM_CONN_STATUS_INPROGRESS;
-		tstconn->fd = proxy_connect(host, port, oscar_chatnav_connect, ic);
-		if (tstconn->fd < 0) {
-			aim_conn_kill(sess, &tstconn);
-			g_free(host);
-			return 1;
-		}
-		aim_sendcookie(sess, tstconn, redir->cookie);
-		break;
-	case 0xe: /* Chat */
-	{
-		struct chat_connection *ccon;
-
-		tstconn = aim_newconn(sess, AIM_CONN_TYPE_CHAT, NULL);
-		if (tstconn == NULL) {
-			g_free(host);
-			return 1;
-		}
-
-		aim_conn_addhandler(sess, tstconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, conninitdone_chat,
-		                    0);
-
-		ccon = g_new0(struct chat_connection, 1);
-		ccon->conn = tstconn;
-		ccon->ic = ic;
-		ccon->fd = -1;
-		ccon->name = g_strdup(redir->chat.room);
-		ccon->exchange = redir->chat.exchange;
-		ccon->instance = redir->chat.instance;
-		ccon->show = extract_name(redir->chat.room);
-
-		ccon->conn->status |= AIM_CONN_STATUS_INPROGRESS;
-		ccon->conn->fd = proxy_connect(host, port, oscar_chat_connect, ccon);
-		if (ccon->conn->fd < 0) {
-			aim_conn_kill(sess, &tstconn);
-			g_free(host);
-			g_free(ccon->show);
-			g_free(ccon->name);
-			g_free(ccon);
-			return 1;
-		}
-		aim_sendcookie(sess, tstconn, redir->cookie);
-	}
-	break;
-	default: /* huh? */
-		break;
-	}
-
-	g_free(host);
-	return 1;
-}
-
-static int gaim_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	struct im_connection *ic = sess->aux_data;
-	struct oscar_data *od = ic->proto_data;
-	aim_userinfo_t *info;
-	time_t time_idle = 0, signon = 0;
-	int flags = OPT_LOGGED_IN;
-	char *tmp, *state_string = NULL;
-
-	va_list ap;
-
-	va_start(ap, fr);
-	info = va_arg(ap, aim_userinfo_t *);
-	va_end(ap);
-
-	if ((!od->icq) && (info->present & AIM_USERINFO_PRESENT_FLAGS)) {
-		if (info->flags & AIM_FLAG_AWAY) {
-			flags |= OPT_AWAY;
-		}
-	}
-
-	/* Maybe this should be done just for AIM contacts, not sure. */
-	if (info->flags & AIM_FLAG_WIRELESS) {
-		flags |= OPT_MOBILE;
-	}
-
-	if (info->present & AIM_USERINFO_PRESENT_ICQEXTSTATUS) {
-		if (!(info->icqinfo.status & AIM_ICQ_STATE_CHAT) &&
-		    (info->icqinfo.status != AIM_ICQ_STATE_NORMAL)) {
-			flags |= OPT_AWAY;
-		}
-
-		if (info->icqinfo.status & AIM_ICQ_STATE_DND) {
-			state_string = "Do Not Disturb";
-		} else if (info->icqinfo.status & AIM_ICQ_STATE_OUT) {
-			state_string = "Not Available";
-		} else if (info->icqinfo.status & AIM_ICQ_STATE_BUSY) {
-			state_string = "Occupied";
-		} else if (info->icqinfo.status & AIM_ICQ_STATE_INVISIBLE) {
-			state_string = "Invisible";
-		}
-	}
-
-	if (info->present & AIM_USERINFO_PRESENT_IDLE) {
-		time(&time_idle);
-		time_idle -= info->idletime * 60;
-	}
-
-	if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN) {
-		signon = time(NULL) - info->sessionlen;
-	}
-
-	if (info->present & AIM_USERINFO_PRESENT_ICQIPADDR) {
-		uint32_t *uin = g_new0(uint32_t, 1);
-
-		if (od->ips == NULL) {
-			od->ips = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
-		}
-
-		if (sscanf(info->sn, "%d", uin) == 1) {
-			g_hash_table_insert(od->ips, uin, (gpointer) (long) info->icqinfo.ipaddr);
-		}
-	}
-
-	tmp = normalize(info->sn);
-	imcb_buddy_status(ic, tmp, flags, state_string, NULL);
-	imcb_buddy_times(ic, tmp, signon, time_idle);
-
-
-	return 1;
-}
-
-static int gaim_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	aim_userinfo_t *info;
-	va_list ap;
-	struct im_connection *ic = sess->aux_data;
-
-	va_start(ap, fr);
-	info = va_arg(ap, aim_userinfo_t *);
-	va_end(ap);
-
-	imcb_buddy_status(ic, normalize(info->sn), 0, NULL, NULL);
-
-	return 1;
-}
-
-static int incomingim_chan1(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo,
-                            struct aim_incomingim_ch1_args *args)
-{
-	char *tmp = g_malloc(BUF_LONG + 1);
-	struct im_connection *ic = sess->aux_data;
-	int flags = 0;
-
-	if (args->icbmflags & AIM_IMFLAGS_AWAY) {
-		flags |= OPT_AWAY;
-	}
-
-	if ((args->icbmflags & AIM_IMFLAGS_UNICODE) || (args->icbmflags & AIM_IMFLAGS_ISO_8859_1)) {
-		char *src;
-
-		if (args->icbmflags & AIM_IMFLAGS_UNICODE) {
-			src = "UCS-2BE";
-		} else {
-			src = "ISO8859-1";
-		}
-
-		/* Try to use iconv first to convert the message to UTF8 - which is what BitlBee expects */
-		if (do_iconv(src, "UTF-8", args->msg, tmp, args->msglen, BUF_LONG) >= 0) {
-			// Successfully converted!
-		} else if (args->icbmflags & AIM_IMFLAGS_UNICODE) {
-			int i;
-
-			for (i = 0, tmp[0] = '\0'; i < args->msglen; i += 2) {
-				unsigned short uni;
-
-				uni = ((args->msg[i] & 0xff) << 8) | (args->msg[i + 1] & 0xff);
-
-				if ((uni < 128) || ((uni >= 160) && (uni <= 255))) { /* ISO 8859-1 */
-					g_snprintf(tmp + strlen(tmp), BUF_LONG - strlen(tmp), "%c", uni);
-				} else { /* something else, do UNICODE entity */
-					g_snprintf(tmp + strlen(tmp), BUF_LONG - strlen(tmp), "&#%04x;", uni);
-				}
-			}
-		} else {
-			g_snprintf(tmp, BUF_LONG, "%s", args->msg);
-		}
-	} else if (args->mpmsg.numparts == 0) {
-		g_snprintf(tmp, BUF_LONG, "%s", args->msg);
-	} else {
-		aim_mpmsg_section_t *part;
-
-		*tmp = 0;
-		for (part = args->mpmsg.parts; part; part = part->next) {
-			if (part->data) {
-				g_strlcat(tmp, (char *) part->data, BUF_LONG);
-				g_strlcat(tmp, "\n", BUF_LONG);
-			}
-		}
-	}
-
-	strip_linefeed(tmp);
-	imcb_buddy_msg(ic, normalize(userinfo->sn), tmp, flags, 0);
-	g_free(tmp);
-
-	return 1;
-}
-
-void oscar_accept_chat(void *data);
-void oscar_reject_chat(void *data);
-
-static int incomingim_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo,
-                            struct aim_incomingim_ch2_args *args)
-{
-	struct im_connection *ic = sess->aux_data;
-
-	if (args->status != AIM_RENDEZVOUS_PROPOSE) {
-		return 1;
-	}
-
-	if (args->reqclass & AIM_CAPS_CHAT) {
-		char *name = extract_name(args->info.chat.roominfo.name);
-		int *exch = g_new0(int, 1);
-		GList *m = NULL;
-		char txt[1024];
-		struct aim_chat_invitation * inv = g_new0(struct aim_chat_invitation, 1);
-
-		m = g_list_append(m, g_strdup(name ? name : args->info.chat.roominfo.name));
-		*exch = args->info.chat.roominfo.exchange;
-		m = g_list_append(m, exch);
-
-		g_snprintf(txt, 1024, "Got an invitation to chatroom %s from %s: %s", name, userinfo->sn, args->msg);
-
-		inv->ic = ic;
-		inv->exchange = *exch;
-		inv->name = g_strdup(name);
-
-		imcb_ask(ic, txt, inv, oscar_accept_chat, oscar_reject_chat);
-
-		if (name) {
-			g_free(name);
-		}
-	} else if (args->reqclass & AIM_CAPS_ICQRTF) {
-		// TODO: constify
-		char text[strlen(args->info.rtfmsg.rtfmsg) + 1];
-		strncpy(text, args->info.rtfmsg.rtfmsg, sizeof(text));
-		imcb_buddy_msg(ic, normalize(userinfo->sn), text, 0, 0);
-	}
-
-	return 1;
-}
-
-static void gaim_icq_authgrant(void *data_)
-{
-	struct icq_auth *data = data_;
-	char *uin;
-	struct oscar_data *od = (struct oscar_data *) data->ic->proto_data;
-
-	uin = g_strdup_printf("%u", data->uin);
-	aim_ssi_auth_reply(od->sess, od->conn, uin, 1, "");
-	// char *message = 0;
-	// aim_send_im_ch4(od->sess, uin, AIM_ICQMSG_AUTHGRANTED, &message);
-	imcb_ask_add(data->ic, uin, NULL);
-
-	g_free(uin);
-	g_free(data);
-}
-
-static void gaim_icq_authdeny(void *data_)
-{
-	struct icq_auth *data = data_;
-	char *uin, *message;
-	struct oscar_data *od = (struct oscar_data *) data->ic->proto_data;
-
-	uin = g_strdup_printf("%u", data->uin);
-	message = g_strdup_printf("No reason given.");
-	aim_ssi_auth_reply(od->sess, od->conn, uin, 0, "");
-	// aim_send_im_ch4(od->sess, uin, AIM_ICQMSG_AUTHDENIED, message);
-	g_free(message);
-
-	g_free(uin);
-	g_free(data);
-}
-
-/*
- * For when other people ask you for authorization
- */
-static void gaim_icq_authask(struct im_connection *ic, guint32 uin, char *msg)
-{
-	struct icq_auth *data;
-	char *reason = NULL;
-	char *dialog_msg;
-
-	if (set_getbool(&ic->acc->set, "ignore_auth_requests")) {
-		return;
-	}
-
-	data = g_new(struct icq_auth, 1);
-
-	if (strlen(msg) > 6) {
-		reason = msg + 6;
-	}
-
-	dialog_msg = g_strdup_printf("The user %u wants to add you to their buddy list for the following reason: %s",
-	                             uin, reason ? reason : "No reason given.");
-	data->ic = ic;
-	data->uin = uin;
-	imcb_ask(ic, dialog_msg, data, gaim_icq_authgrant, gaim_icq_authdeny);
-	g_free(dialog_msg);
-}
-
-static int incomingim_chan4(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *userinfo,
-                            struct aim_incomingim_ch4_args *args)
-{
-	struct im_connection *ic = sess->aux_data;
-
-	switch (args->type) {
-	case 0x0001: {         /* An almost-normal instant message.  Mac ICQ sends this.  It's peculiar. */
-		char *uin, *message;
-		uin = g_strdup_printf("%u", args->uin);
-		message = g_strdup(args->msg);
-		strip_linefeed(message);
-		imcb_buddy_msg(ic, normalize(uin), message, 0, 0);
-		g_free(uin);
-		g_free(message);
-	} break;
-
-	case 0x0004: {         /* Someone sent you a URL */
-		char *uin, *message;
-		char **m;
-
-		uin = g_strdup_printf("%u", args->uin);
-		m = g_strsplit(args->msg, "\376", 2);
-
-		if ((strlen(m[0]) != 0)) {
-			message = g_strjoinv(" -- ", m);
-		} else {
-			message = m[1];
-		}
-
-		strip_linefeed(message);
-		imcb_buddy_msg(ic, normalize(uin), message, 0, 0);
-		g_free(uin);
-		g_free(m);
-		g_free(message);
-	} break;
-
-	case 0x0006: {         /* Someone requested authorization */
-		gaim_icq_authask(ic, args->uin, args->msg);
-	} break;
-
-	case 0x0007: {         /* Someone has denied you authorization */
-		imcb_log(sess->aux_data,
-		         "The user %u has denied your request to add them to your contact list for the following reason:\n%s", args->uin,
-		         args->msg ? args->msg : _("No reason given."));
-	} break;
-
-	case 0x0008: {         /* Someone has granted you authorization */
-		imcb_log(sess->aux_data,
-		         "The user %u has granted your request to add them to your contact list for the following reason:\n%s", args->uin,
-		         args->msg ? args->msg : _("No reason given."));
-	} break;
-
-	case 0x0012: {
-		/* Ack for authorizing/denying someone.  Or possibly an ack for sending any system notice */
-	} break;
-
-	default: {; } break;
-	}
-
-	return 1;
-}
-
-static int gaim_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	int channel, ret = 0;
-	aim_userinfo_t *userinfo;
-	va_list ap;
-
-	va_start(ap, fr);
-	channel = va_arg(ap, int);
-	userinfo = va_arg(ap, aim_userinfo_t *);
-
-	switch (channel) {
-	case 1: {         /* standard message */
-		struct aim_incomingim_ch1_args *args;
-		args = va_arg(ap, struct aim_incomingim_ch1_args *);
-		ret = incomingim_chan1(sess, fr->conn, userinfo, args);
-	} break;
-
-	case 2: {         /* rendezvous */
-		struct aim_incomingim_ch2_args *args;
-		args = va_arg(ap, struct aim_incomingim_ch2_args *);
-		ret = incomingim_chan2(sess, fr->conn, userinfo, args);
-	} break;
-
-	case 4: {         /* ICQ */
-		struct aim_incomingim_ch4_args *args;
-		args = va_arg(ap, struct aim_incomingim_ch4_args *);
-		ret = incomingim_chan4(sess, fr->conn, userinfo, args);
-	} break;
-
-	default: {; } break;
-	}
-
-	va_end(ap);
-
-	return ret;
-}
-
-static int gaim_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	va_list ap;
-	guint16 nummissed, reason;
-	aim_userinfo_t *userinfo;
-
-	va_start(ap, fr);
-	va_arg(ap, unsigned int); /* chan */
-	userinfo = va_arg(ap, aim_userinfo_t *);
-	nummissed = (guint16) va_arg(ap, unsigned int);
-	reason = (guint16) va_arg(ap, unsigned int);
-	va_end(ap);
-
-	switch (reason) {
-	case 0:
-		/* Invalid (0) */
-		imcb_error(sess->aux_data,
-		           nummissed == 1 ?
-		           _("You missed %d message from %s because it was invalid.") :
-		           _("You missed %d messages from %s because they were invalid."),
-		           nummissed,
-		           userinfo->sn);
-		break;
-	case 1:
-		/* Message too large */
-		imcb_error(sess->aux_data,
-		           nummissed == 1 ?
-		           _("You missed %d message from %s because it was too large.") :
-		           _("You missed %d messages from %s because they were too large."),
-		           nummissed,
-		           userinfo->sn);
-		break;
-	case 2:
-		/* Rate exceeded */
-		imcb_error(sess->aux_data,
-		           nummissed == 1 ?
-		           _("You missed %d message from %s because the rate limit has been exceeded.") :
-		           _("You missed %d messages from %s because the rate limit has been exceeded."),
-		           nummissed,
-		           userinfo->sn);
-		break;
-	case 3:
-		/* Evil Sender */
-		imcb_error(sess->aux_data,
-		           nummissed == 1 ?
-		           _("You missed %d message from %s because it was too evil.") :
-		           _("You missed %d messages from %s because they are too evil."),
-		           nummissed,
-		           userinfo->sn);
-		break;
-	case 4:
-		/* Evil Receiver */
-		imcb_error(sess->aux_data,
-		           nummissed == 1 ?
-		           _("You missed %d message from %s because you are too evil.") :
-		           _("You missed %d messages from %s because you are too evil."),
-		           nummissed,
-		           userinfo->sn);
-		break;
-	default:
-		imcb_error(sess->aux_data,
-		           nummissed == 1 ?
-		           _("You missed %d message from %s for unknown reasons.") :
-		           _("You missed %d messages from %s for unknown reasons."),
-		           nummissed,
-		           userinfo->sn);
-		break;
-	}
-
-	return 1;
-}
-
-static int gaim_parse_genericerr(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	va_list ap;
-	guint16 reason;
-
-	va_start(ap, fr);
-	reason = (guint16) va_arg(ap, unsigned int);
-	va_end(ap);
-
-	imcb_error(sess->aux_data, _("SNAC threw error: %s"),
-	           reason < msgerrreasonlen ? msgerrreason[reason] : "Unknown error");
-
-	return 1;
-}
-
-static int gaim_parse_msgerr(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	va_list ap;
-	char *destn;
-	guint16 reason;
-
-	va_start(ap, fr);
-	reason = (guint16) va_arg(ap, unsigned int);
-	destn = va_arg(ap, char *);
-	va_end(ap);
-
-	imcb_error(sess->aux_data, _("Your message to %s did not get sent: %s"), destn,
-	           (reason < msgerrreasonlen) ? msgerrreason[reason] : _("Reason unknown"));
-
-	return 1;
-}
-
-static int gaim_parse_locerr(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	va_list ap;
-	char *destn;
-	guint16 reason;
-
-	va_start(ap, fr);
-	reason = (guint16) va_arg(ap, unsigned int);
-	destn = va_arg(ap, char *);
-	va_end(ap);
-
-	imcb_error(sess->aux_data, _("User information for %s unavailable: %s"), destn,
-	           (reason < msgerrreasonlen) ? msgerrreason[reason] : _("Reason unknown"));
-
-	return 1;
-}
-
-static int gaim_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	guint16 id;
-	va_list ap;
-
-	va_start(ap, fr);
-	id  = (guint16) va_arg(ap, unsigned int);
-	va_arg(ap, char *); /* msg */
-	va_end(ap);
-
-	if (id < 4) {
-		imcb_error(sess->aux_data, _("Your connection may be lost."));
-	}
-
-	return 1;
-}
-
-static int gaim_chatnav_info(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	va_list ap;
-	guint16 type;
-	struct im_connection *ic = sess->aux_data;
-	struct oscar_data *odata = (struct oscar_data *) ic->proto_data;
-
-	va_start(ap, fr);
-	type = (guint16) va_arg(ap, unsigned int);
-
-	switch (type) {
-	case 0x0002: {
-		va_arg(ap, unsigned int);         /* maxrooms */
-		va_arg(ap, int);         /* exchangecount */
-		va_arg(ap, struct aim_chat_exchangeinfo *);         /* exchanges */
-		va_end(ap);
-
-		while (odata->create_rooms) {
-			struct create_room *cr = odata->create_rooms->data;
-			aim_chatnav_createroom(sess, fr->conn, cr->name, cr->exchange);
-			g_free(cr->name);
-			odata->create_rooms = g_slist_remove(odata->create_rooms, cr);
-			g_free(cr);
-		}
-	}
-	break;
-	case 0x0008: {
-		char *ck;
-		guint16 instance, exchange;
-
-		va_arg(ap, char *);         /* fqcn */
-		instance = (guint16) va_arg(ap, unsigned int);
-		exchange = (guint16) va_arg(ap, unsigned int);
-		va_arg(ap, unsigned int);         /* flags */
-		va_arg(ap, guint32);         /* createtime */
-		va_arg(ap, unsigned int);         /* maxmsglen */
-		va_arg(ap, unsigned int);         /* maxoccupancy */
-		va_arg(ap, int);         /* createperms */
-		va_arg(ap, unsigned int);         /* unknown */
-		va_arg(ap, char *);         /* name */
-		ck = va_arg(ap, char *);
-		va_end(ap);
-
-		aim_chat_join(odata->sess, odata->conn, exchange, ck, instance);
-	}
-	break;
-	default:
-		va_end(ap);
-		break;
-	}
-	return 1;
-}
-
-static int gaim_chat_join(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	va_list ap;
-	int count, i;
-	aim_userinfo_t *info;
-	struct im_connection *g = sess->aux_data;
-
-	struct chat_connection *c = NULL;
-
-	va_start(ap, fr);
-	count = va_arg(ap, int);
-	info  = va_arg(ap, aim_userinfo_t *);
-	va_end(ap);
-
-	c = find_oscar_chat_by_conn(g, fr->conn);
-	if (!c) {
-		return 1;
-	}
-
-	for (i = 0; i < count; i++) {
-		imcb_chat_add_buddy(c->cnv, normalize(info[i].sn));
-	}
-
-	return 1;
-}
-
-static int gaim_chat_leave(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	va_list ap;
-	int count, i;
-	aim_userinfo_t *info;
-	struct im_connection *g = sess->aux_data;
-
-	struct chat_connection *c = NULL;
-
-	va_start(ap, fr);
-	count = va_arg(ap, int);
-	info  = va_arg(ap, aim_userinfo_t *);
-	va_end(ap);
-
-	c = find_oscar_chat_by_conn(g, fr->conn);
-	if (!c) {
-		return 1;
-	}
-
-	for (i = 0; i < count; i++) {
-		imcb_chat_remove_buddy(c->cnv, normalize(info[i].sn), NULL);
-	}
-
-	return 1;
-}
-
-static int gaim_chat_info_update(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	va_list ap;
-	guint16 maxmsglen, maxvisiblemsglen;
-	struct im_connection *ic = sess->aux_data;
-	struct chat_connection *ccon = find_oscar_chat_by_conn(ic, fr->conn);
-
-	va_start(ap, fr);
-	va_arg(ap, struct aim_chat_roominfo *); /* roominfo */
-	va_arg(ap, char *); /* roomname */
-	va_arg(ap, int); /* usercount */
-	va_arg(ap, aim_userinfo_t *); /* userinfo */
-	va_arg(ap, char *); /* roomdesc */
-	va_arg(ap, int); /* unknown_c9 */
-	va_arg(ap, unsigned long); /* creationtime */
-	maxmsglen = (guint16) va_arg(ap, int);
-	va_arg(ap, int); /* unknown_d2 */
-	va_arg(ap, int); /* unknown_d5 */
-	maxvisiblemsglen = (guint16) va_arg(ap, int);
-	va_end(ap);
-
-	ccon->maxlen = maxmsglen;
-	ccon->maxvis = maxvisiblemsglen;
-
-	return 1;
-}
-
-static int gaim_chat_incoming_msg(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	va_list ap;
-	aim_userinfo_t *info;
-	char *msg;
-	struct im_connection *ic = sess->aux_data;
-	struct chat_connection *ccon = find_oscar_chat_by_conn(ic, fr->conn);
-	char *tmp;
-
-	va_start(ap, fr);
-	info = va_arg(ap, aim_userinfo_t *);
-	msg  = va_arg(ap, char *);
-
-	tmp = g_malloc(BUF_LONG);
-	g_snprintf(tmp, BUF_LONG, "%s", msg);
-	imcb_chat_msg(ccon->cnv, normalize(info->sn), tmp, 0, 0);
-	g_free(tmp);
-
-	return 1;
-}
-
-static int gaim_parse_ratechange(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-#if 0
-	static const char *codes[5] = {
-		"invalid",
-		"change",
-		"warning",
-		"limit",
-		"limit cleared",
-	};
-#endif
-	va_list ap;
-	guint16 code;
-	guint32 windowsize, clear, currentavg;
-
-	va_start(ap, fr);
-	code = (guint16) va_arg(ap, unsigned int);
-	va_arg(ap, unsigned int); /* rateclass */
-	windowsize = (guint32) va_arg(ap, unsigned long);
-	clear = (guint32) va_arg(ap, unsigned long);
-	va_arg(ap, unsigned long); /* alert */
-	va_arg(ap, unsigned long); /* limit */
-	va_arg(ap, unsigned long); /* disconnect */
-	currentavg = (guint32) va_arg(ap, unsigned long);
-	va_arg(ap, unsigned long); /* maxavg */
-	va_end(ap);
-
-	/* XXX fix these values */
-	if (code == AIM_RATE_CODE_CHANGE) {
-		if (currentavg >= clear) {
-			aim_conn_setlatency(fr->conn, 0);
-		}
-	} else if (code == AIM_RATE_CODE_WARNING) {
-		aim_conn_setlatency(fr->conn, windowsize / 4);
-	} else if (code == AIM_RATE_CODE_LIMIT) {
-		imcb_error(sess->aux_data, _("The last message was not sent because you are over the rate limit. "
-		                             "Please wait 10 seconds and try again."));
-		aim_conn_setlatency(fr->conn, windowsize / 2);
-	} else if (code == AIM_RATE_CODE_CLEARLIMIT) {
-		aim_conn_setlatency(fr->conn, 0);
-	}
-
-	return 1;
-}
-
-static int gaim_selfinfo(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	return 1;
-}
-
-static int conninitdone_bos(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-
-	aim_reqpersonalinfo(sess, fr->conn);
-	aim_bos_reqlocaterights(sess, fr->conn);
-	aim_bos_reqbuddyrights(sess, fr->conn);
-
-	aim_reqicbmparams(sess);
-
-	aim_bos_reqrights(sess, fr->conn);
-	aim_bos_setgroupperm(sess, fr->conn, AIM_FLAG_ALLUSERS);
-	aim_bos_setprivacyflags(sess, fr->conn, AIM_PRIVFLAGS_ALLOWIDLE |
-	                        AIM_PRIVFLAGS_ALLOWMEMBERSINCE);
-
-	return 1;
-}
-
-static int conninitdone_admin(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	struct im_connection *ic = sess->aux_data;
-	struct oscar_data *od = ic->proto_data;
-
-	aim_clientready(sess, fr->conn);
-
-	if (od->chpass) {
-		aim_admin_changepasswd(sess, fr->conn, od->newp, od->oldp);
-		g_free(od->oldp);
-		od->oldp = NULL;
-		g_free(od->newp);
-		od->newp = NULL;
-		od->chpass = FALSE;
-	}
-	if (od->setnick) {
-		aim_admin_setnick(sess, fr->conn, od->newsn);
-		g_free(od->newsn);
-		od->newsn = NULL;
-		od->setnick = FALSE;
-	}
-	if (od->conf) {
-		aim_admin_reqconfirm(sess, fr->conn);
-		od->conf = FALSE;
-	}
-	if (od->reqemail) {
-		aim_admin_getinfo(sess, fr->conn, 0x0011);
-		od->reqemail = FALSE;
-	}
-	if (od->setemail) {
-		aim_admin_setemail(sess, fr->conn, od->email);
-		g_free(od->email);
-		od->setemail = FALSE;
-	}
-
-	return 1;
-}
-
-static int gaim_icbm_param_info(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	struct aim_icbmparameters *params;
-	va_list ap;
-
-	va_start(ap, fr);
-	params = va_arg(ap, struct aim_icbmparameters *);
-	va_end(ap);
-
-	/* Maybe senderwarn and recverwarn should be user preferences... */
-	params->flags = 0x0000000b;
-	params->maxmsglen = 8000;
-	params->minmsginterval = 0;
-
-	aim_seticbmparam(sess, params);
-
-	return 1;
-}
-
-static int gaim_parse_locaterights(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	va_list ap;
-	guint16 maxsiglen;
-	struct im_connection *ic = sess->aux_data;
-	struct oscar_data *odata = (struct oscar_data *) ic->proto_data;
-
-	va_start(ap, fr);
-	maxsiglen = va_arg(ap, int);
-	va_end(ap);
-
-	odata->rights.maxsiglen = odata->rights.maxawaymsglen = (guint) maxsiglen;
-
-	/* FIXME: It seems we're not really using this, and it broke now that
-	   struct aim_user is dead.
-	aim_bos_setprofile(sess, fr->conn, ic->user->user_info, NULL, gaim_caps);
-	*/
-
-	return 1;
-}
-
-static int gaim_parse_buddyrights(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	va_list ap;
-	guint16 maxbuddies, maxwatchers;
-	struct im_connection *ic = sess->aux_data;
-	struct oscar_data *odata = (struct oscar_data *) ic->proto_data;
-
-	va_start(ap, fr);
-	maxbuddies = (guint16) va_arg(ap, unsigned int);
-	maxwatchers = (guint16) va_arg(ap, unsigned int);
-	va_end(ap);
-
-	odata->rights.maxbuddies = (guint) maxbuddies;
-	odata->rights.maxwatchers = (guint) maxwatchers;
-
-	return 1;
-}
-
-static int gaim_bosrights(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	guint16 maxpermits, maxdenies;
-	va_list ap;
-	struct im_connection *ic = sess->aux_data;
-	struct oscar_data *odata = (struct oscar_data *) ic->proto_data;
-
-	va_start(ap, fr);
-	maxpermits = (guint16) va_arg(ap, unsigned int);
-	maxdenies = (guint16) va_arg(ap, unsigned int);
-	va_end(ap);
-
-	odata->rights.maxpermits = (guint) maxpermits;
-	odata->rights.maxdenies = (guint) maxdenies;
-
-	aim_clientready(sess, fr->conn);
-
-	aim_reqservice(sess, fr->conn, AIM_CONN_TYPE_CHATNAV);
-
-	aim_ssi_reqrights(sess, fr->conn);
-	aim_ssi_reqalldata(sess, fr->conn);
-
-	return 1;
-}
-
-static int gaim_offlinemsg(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	va_list ap;
-	struct aim_icq_offlinemsg *msg;
-	struct im_connection *ic = sess->aux_data;
-
-	va_start(ap, fr);
-	msg = va_arg(ap, struct aim_icq_offlinemsg *);
-	va_end(ap);
-
-	switch (msg->type) {
-	case 0x0001: {         /* Basic offline message */
-		char sender[32];
-		char *dialog_msg = g_strdup(msg->msg);
-		time_t t = get_time(msg->year, msg->month, msg->day, msg->hour, msg->minute, 0);
-		g_snprintf(sender, sizeof(sender), "%u", msg->sender);
-		strip_linefeed(dialog_msg);
-		imcb_buddy_msg(ic, normalize(sender), dialog_msg, 0, t);
-		g_free(dialog_msg);
-	} break;
-
-	case 0x0004: {         /* Someone sent you a URL */
-		char sender[32];
-		char *dialog_msg;
-		char **m;
-
-		time_t t = get_time(msg->year, msg->month, msg->day, msg->hour, msg->minute, 0);
-		g_snprintf(sender, sizeof(sender), "%u", msg->sender);
-
-		m = g_strsplit(msg->msg, "\376", 2);
-
-		if ((strlen(m[0]) != 0)) {
-			dialog_msg = g_strjoinv(" -- ", m);
-		} else {
-			dialog_msg = m[1];
-		}
-
-		strip_linefeed(dialog_msg);
-		imcb_buddy_msg(ic, normalize(sender), dialog_msg, 0, t);
-		g_free(dialog_msg);
-		g_free(m);
-	} break;
-
-	case 0x0006: {         /* Authorization request */
-		gaim_icq_authask(ic, msg->sender, msg->msg);
-	} break;
-
-	case 0x0007: {         /* Someone has denied you authorization */
-		imcb_log(sess->aux_data,
-		         "The user %u has denied your request to add them to your contact list for the following reason:\n%s", msg->sender,
-		         msg->msg ? msg->msg : _("No reason given."));
-	} break;
-
-	case 0x0008: {         /* Someone has granted you authorization */
-		imcb_log(sess->aux_data,
-		         "The user %u has granted your request to add them to your contact list for the following reason:\n%s", msg->sender,
-		         msg->msg ? msg->msg : _("No reason given."));
-	} break;
-
-	case 0x0012: {
-		/* Ack for authorizing/denying someone.  Or possibly an ack for sending any system notice */
-	} break;
-
-	default: {; }
-	}
-
-	return 1;
-}
-
-static int gaim_offlinemsgdone(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	aim_icq_ackofflinemsgs(sess);
-	return 1;
-}
-
-static void oscar_keepalive(struct im_connection *ic)
-{
-	struct oscar_data *odata = (struct oscar_data *) ic->proto_data;
-
-	aim_flap_nop(odata->sess, odata->conn);
-}
-
-static int oscar_buddy_msg(struct im_connection *ic, char *name, char *message, int imflags)
-{
-	struct oscar_data *odata = (struct oscar_data *) ic->proto_data;
-	int ret = 0, len = strlen(message);
-
-	if (imflags & OPT_AWAY) {
-		ret = aim_send_im(odata->sess, name, AIM_IMFLAGS_AWAY, message);
-	} else {
-		struct aim_sendimext_args args;
-		char *s;
-
-		args.flags = AIM_IMFLAGS_ACK;
-		if (odata->icq) {
-			args.flags |= AIM_IMFLAGS_OFFLINE;
-		}
-		for (s = message; *s; s++) {
-			if (*s & 128) {
-				break;
-			}
-		}
-
-		/* Message contains high ASCII chars, time for some translation! */
-		if (*s) {
-			s = g_malloc(BUF_LONG);
-			/* Try if we can put it in an ISO8859-1 string first.
-			   If we can't, fall back to UTF16. */
-			if ((ret = do_iconv("UTF-8", "ISO8859-1", message, s, len, BUF_LONG)) >= 0) {
-				args.flags |= AIM_IMFLAGS_ISO_8859_1;
-				len = ret;
-			} else if ((ret = do_iconv("UTF-8", "UCS-2BE", message, s, len, BUF_LONG)) >= 0) {
-				args.flags |= AIM_IMFLAGS_UNICODE;
-				len = ret;
-			} else {
-				/* OOF, translation failed... Oh well.. */
-				g_free(s);
-				s = message;
-			}
-		} else {
-			s = message;
-		}
-
-		args.features = gaim_features;
-		args.featureslen = sizeof(gaim_features);
-
-		args.destsn = name;
-		args.msg    = s;
-		args.msglen = len;
-
-		ret = aim_send_im_ext(odata->sess, &args);
-
-		if (s != message) {
-			g_free(s);
-		}
-	}
-	if (ret >= 0) {
-		return 1;
-	}
-	return ret;
-}
-
-static void oscar_get_info(struct im_connection *g, char *name)
-{
-	struct oscar_data *odata = (struct oscar_data *) g->proto_data;
-
-	if (odata->icq) {
-		aim_icq_getallinfo(odata->sess, name);
-	} else {
-		aim_getinfo(odata->sess, odata->conn, name, AIM_GETINFO_AWAYMESSAGE);
-		aim_getinfo(odata->sess, odata->conn, name, AIM_GETINFO_GENERALINFO);
-	}
-}
-
-static void oscar_set_away_aim(struct im_connection *ic, struct oscar_data *od, const char *state, const char *message)
-{
-	if (state == NULL) {
-		state = "";
-	}
-
-	if (!g_strcasecmp(state, _("Visible"))) {
-		aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL);
-		return;
-	} else if (!g_strcasecmp(state, _("Invisible"))) {
-		aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_INVISIBLE);
-		return;
-	} else if (message == NULL) {
-		message = state;
-	}
-
-	if (od->rights.maxawaymsglen == 0) {
-		imcb_error(ic, "oscar_set_away_aim called before locate rights received");
-	}
-
-	aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL);
-
-	g_free(ic->away);
-	ic->away = NULL;
-
-	if (!message) {
-		aim_bos_setprofile(od->sess, od->conn, NULL, "", gaim_caps);
-		return;
-	}
-
-	if (strlen(message) > od->rights.maxawaymsglen) {
-		imcb_error(ic, "Maximum away message length of %d bytes exceeded, truncating",
-		           od->rights.maxawaymsglen);
-	}
-
-	ic->away = g_strndup(message, od->rights.maxawaymsglen);
-	aim_bos_setprofile(od->sess, od->conn, NULL, ic->away, gaim_caps);
-
-	return;
-}
-
-static void oscar_set_away_icq(struct im_connection *ic, struct oscar_data *od, const char *state, const char *message)
-{
-	const char *msg = NULL;
-	gboolean no_message = FALSE;
-
-	/* clean old states */
-	g_free(ic->away);
-	ic->away = NULL;
-	od->sess->aim_icq_state = 0;
-
-	/* if no message, then use an empty message */
-	if (message) {
-		msg = message;
-	} else {
-		msg = "";
-		no_message = TRUE;
-	}
-
-	if (state == NULL) {
-		aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL);
-	} else if (!g_strcasecmp(state, "Away")) {
-		aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_AWAY);
-		ic->away = g_strdup(msg);
-		od->sess->aim_icq_state = AIM_MTYPE_AUTOAWAY;
-	} else if (!g_strcasecmp(state, "Do Not Disturb")) {
-		aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_DND | AIM_ICQ_STATE_BUSY);
-		ic->away = g_strdup(msg);
-		od->sess->aim_icq_state = AIM_MTYPE_AUTODND;
-	} else if (!g_strcasecmp(state, "Not Available")) {
-		aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_OUT | AIM_ICQ_STATE_AWAY);
-		ic->away = g_strdup(msg);
-		od->sess->aim_icq_state = AIM_MTYPE_AUTONA;
-	} else if (!g_strcasecmp(state, "Occupied")) {
-		aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_BUSY);
-		ic->away = g_strdup(msg);
-		od->sess->aim_icq_state = AIM_MTYPE_AUTOBUSY;
-	} else if (!g_strcasecmp(state, "Free For Chat")) {
-		aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_CHAT);
-		ic->away = g_strdup(msg);
-		od->sess->aim_icq_state = AIM_MTYPE_AUTOFFC;
-	} else if (!g_strcasecmp(state, "Invisible")) {
-		aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_INVISIBLE);
-		ic->away = g_strdup(msg);
-	} else {
-		if (no_message) {
-			aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_NORMAL);
-		} else {
-			aim_setextstatus(od->sess, od->conn, AIM_ICQ_STATE_AWAY);
-			ic->away = g_strdup(msg);
-			od->sess->aim_icq_state = AIM_MTYPE_AUTOAWAY;
-		}
-	}
-
-	return;
-}
-
-static void oscar_set_away(struct im_connection *ic, char *state, char *message)
-{
-	struct oscar_data *od = (struct oscar_data *) ic->proto_data;
-
-	oscar_set_away_aim(ic, od, state, message);
-	if (od->icq) {
-		oscar_set_away_icq(ic, od, state, message);
-	}
-
-	return;
-}
-
-static void oscar_add_buddy(struct im_connection *g, char *name, char *group)
-{
-	struct oscar_data *odata = (struct oscar_data *) g->proto_data;
-	bee_user_t *bu;
-
-	if (group && (bu = bee_user_by_handle(g->bee, g, name)) && bu->group) {
-		aim_ssi_movebuddy(odata->sess, odata->conn, bu->group->name, group, name);
-	} else {
-		aim_ssi_addbuddies(odata->sess, odata->conn, group ? : OSCAR_GROUP, &name, 1, 0);
-	}
-}
-
-static void oscar_remove_buddy(struct im_connection *g, char *name, char *group)
-{
-	struct oscar_data *odata = (struct oscar_data *) g->proto_data;
-	struct aim_ssi_item *ssigroup;
-
-	while ((ssigroup =
-	                aim_ssi_itemlist_findparent(odata->sess->ssi.items,
-	                                            name)) &&
-	       !aim_ssi_delbuddies(odata->sess, odata->conn, ssigroup->name, &name, 1)) {
-		;
-	}
-}
-
-static int gaim_ssi_parserights(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	return 1;
-}
-
-static int gaim_ssi_parselist(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	struct im_connection *ic = sess->aux_data;
-	struct aim_ssi_item *curitem, *curgroup = NULL;
-	int tmp;
-	char *nrm;
-
-	/* Add from server list to local list */
-	tmp = 0;
-	for (curitem = sess->ssi.items; curitem; curitem = curitem->next) {
-		nrm = curitem->name ? normalize(curitem->name) : NULL;
-
-		switch (curitem->type) {
-		case 0x0000:         /* Buddy */
-			if ((curitem->name) && (!imcb_buddy_by_handle(ic, nrm))) {
-				char *realname = NULL;
-
-				if (curitem->data && aim_gettlv(curitem->data, 0x0131, 1)) {
-					realname = aim_gettlv_str(curitem->data, 0x0131, 1);
-				}
-
-				imcb_add_buddy(ic, nrm,
-				               curgroup ? (curgroup->gid ==
-				                           curitem->gid ? curgroup->name : NULL) : NULL);
-
-				if (realname) {
-					imcb_buddy_nick_hint(ic, nrm, realname);
-					imcb_rename_buddy(ic, nrm, realname);
-					g_free(realname);
-				}
-			}
-			break;
-
-		case 0x0001:         /* Group */
-			curgroup = curitem;
-			break;
-
-		case 0x0002:         /* Permit buddy */
-			if (curitem->name) {
-				GSList *list;
-				for (list = ic->permit; (list && aim_sncmp(curitem->name, list->data));
-				     list = list->next) {
-					;
-				}
-				if (!list) {
-					char *name;
-					name = g_strdup(nrm);
-					ic->permit = g_slist_append(ic->permit, name);
-					tmp++;
-				}
-			}
-			break;
-
-		case 0x0003:         /* Deny buddy */
-			if (curitem->name) {
-				GSList *list;
-				for (list = ic->deny;
-				     (list && aim_sncmp(curitem->name, list->data)); list = list->next) {
-					;
-				}
-				if (!list) {
-					char *name;
-					name = g_strdup(nrm);
-					ic->deny = g_slist_append(ic->deny, name);
-					tmp++;
-				}
-			}
-			break;
-
-		case 0x0004:         /* Permit/deny setting */
-			if (curitem->data) {
-				guint8 permdeny;
-				if ((permdeny = aim_ssi_getpermdeny(sess->ssi.items)) && (permdeny != ic->permdeny)) {
-					ic->permdeny = permdeny;
-					tmp++;
-				}
-			}
-			break;
-
-		case 0x0005:         /* Presence setting */
-			/* We don't want to change Gaim's setting because it applies to all accounts */
-			break;
-		} /* End of switch on curitem->type */
-	} /* End of for loop */
-
-	aim_ssi_enable(sess, fr->conn);
-
-	/* Request offline messages, now that the buddy list is complete. */
-	aim_icq_reqofflinemsgs(sess);
-
-	/* Now that we have a buddy list, we can tell BitlBee that we're online. */
-	imcb_connected(ic);
-
-	return 1;
-}
-
-static int gaim_ssi_parseack(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	aim_snac_t *origsnac;
-	va_list ap;
-
-	va_start(ap, fr);
-	origsnac = va_arg(ap, aim_snac_t *);
-	va_end(ap);
-
-	if (origsnac && origsnac->family == AIM_CB_FAM_SSI && origsnac->type == AIM_CB_SSI_ADD && origsnac->data) {
-		int i, st, count = aim_bstream_empty(&fr->data);
-		char *list;
-
-		if (count & 1) {
-			/* Hmm, the length should be even... */
-			imcb_error(sess->aux_data, "Received SSI ACK package with non-even length");
-			return(0);
-		}
-		count >>= 1;
-
-		list = (char *) origsnac->data;
-		for (i = 0; i < count; i++) {
-			struct aim_ssi_item *ssigroup = aim_ssi_itemlist_findparent(sess->ssi.items, list);
-			char *group = ssigroup ? ssigroup->name : NULL;
-
-			st = aimbs_get16(&fr->data);
-			if (st == 0x00) {
-				imcb_add_buddy(sess->aux_data, normalize(list), group);
-			} else if (st == 0x0E) {
-				imcb_log(sess->aux_data,
-				         "Buddy %s can't be added without authorization, requesting authorization",
-				         list);
-
-				aim_ssi_auth_request(sess, fr->conn, list, "");
-				aim_ssi_addbuddies(sess, fr->conn, OSCAR_GROUP, &list, 1, 1);
-			} else if (st == 0x0A) {
-				imcb_error(sess->aux_data, "Buddy %s is already in your list", list);
-			} else {
-				imcb_error(sess->aux_data, "Error while adding buddy: 0x%04x", st);
-			}
-			list += strlen(list) + 1;
-		}
-	}
-
-	return(1);
-}
-
-static void oscar_add_permit(struct im_connection *ic, char *who)
-{
-	struct oscar_data *od = (struct oscar_data *) ic->proto_data;
-
-	if (od->icq) {
-		aim_ssi_auth_reply(od->sess, od->conn, who, 1, "");
-	} else {
-		if (od->sess->ssi.received_data) {
-			aim_ssi_addpord(od->sess, od->conn, &who, 1, AIM_SSI_TYPE_PERMIT);
-		}
-	}
-}
-
-static void oscar_add_deny(struct im_connection *ic, char *who)
-{
-	struct oscar_data *od = (struct oscar_data *) ic->proto_data;
-
-	if (od->icq) {
-		aim_ssi_auth_reply(od->sess, od->conn, who, 0, "");
-	} else {
-		if (od->sess->ssi.received_data) {
-			aim_ssi_addpord(od->sess, od->conn, &who, 1, AIM_SSI_TYPE_DENY);
-		}
-	}
-}
-
-static void oscar_rem_permit(struct im_connection *ic, char *who)
-{
-	struct oscar_data *od = (struct oscar_data *) ic->proto_data;
-
-	if (!od->icq) {
-		if (od->sess->ssi.received_data) {
-			aim_ssi_delpord(od->sess, od->conn, &who, 1, AIM_SSI_TYPE_PERMIT);
-		}
-	}
-}
-
-static void oscar_rem_deny(struct im_connection *ic, char *who)
-{
-	struct oscar_data *od = (struct oscar_data *) ic->proto_data;
-
-	if (!od->icq) {
-		if (od->sess->ssi.received_data) {
-			aim_ssi_delpord(od->sess, od->conn, &who, 1, AIM_SSI_TYPE_DENY);
-		}
-	}
-}
-
-static GList *oscar_away_states(struct im_connection *ic)
-{
-	struct oscar_data *od = ic->proto_data;
-
-	if (od->icq) {
-		static GList *m = NULL;
-		m = g_list_append(m, "Away");
-		m = g_list_append(m, "Do Not Disturb");
-		m = g_list_append(m, "Not Available");
-		m = g_list_append(m, "Occupied");
-		m = g_list_append(m, "Free For Chat");
-		m = g_list_append(m, "Invisible");
-		return m;
-	} else {
-		static GList *m = NULL;
-		m = g_list_append(m, "Away");
-		return m;
-	}
-}
-
-static int gaim_icqinfo(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	struct im_connection *ic = sess->aux_data;
-	struct oscar_data *od = ic->proto_data;
-	gchar who[16];
-	GString *str;
-	va_list ap;
-	struct aim_icq_info *info;
-	uint32_t ip;
-
-	va_start(ap, fr);
-	info = va_arg(ap, struct aim_icq_info *);
-	va_end(ap);
-
-	if (!info->uin) {
-		return 0;
-	}
-
-	str = g_string_sized_new(512);
-	g_snprintf(who, sizeof(who), "%u", info->uin);
-
-	g_string_printf(str, "%s: %s - %s: %s", _("UIN"), who, _("Nick"),
-	                info->nick ? info->nick : "-");
-	g_string_append_printf(str, "\n%s: %s", _("First Name"), info->first);
-	g_string_append_printf(str, "\n%s: %s", _("Last Name"), info->last);
-	g_string_append_printf(str, "\n%s: %s", _("Email Address"), info->email);
-	if (info->numaddresses && info->email2) {
-		int i;
-		for (i = 0; i < info->numaddresses; i++) {
-			g_string_append_printf(str, "\n%s: %s", _("Email Address"), info->email2[i]);
-		}
-	}
-	if (od->ips && (ip = (long) g_hash_table_lookup(od->ips, &info->uin)) != 0) {
-		g_string_append_printf(str, "\n%s: %d.%d.%d.%d", _("Last used IP address"),
-		                       (ip >> 24), (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
-	}
-	g_string_append_printf(str, "\n%s: %s", _("Mobile Phone"), info->mobile);
-	if (info->gender != 0) {
-		g_string_append_printf(str, "\n%s: %s", _("Gender"), info->gender == 1 ? _("Female") : _("Male"));
-	}
-	if (info->birthyear || info->birthmonth || info->birthday) {
-		char date[30];
-		struct tm tm;
-		memset(&tm, 0, sizeof(struct tm));
-		tm.tm_mday = (int) info->birthday;
-		tm.tm_mon = (int) info->birthmonth - 1;
-		tm.tm_year = (int) info->birthyear % 100;
-		strftime(date, sizeof(date), "%Y-%m-%d", &tm);
-		g_string_append_printf(str, "\n%s: %s", _("Birthday"), date);
-	}
-	if (info->age) {
-		char age[5];
-		g_snprintf(age, sizeof(age), "%hhd", info->age);
-		g_string_append_printf(str, "\n%s: %s", _("Age"), age);
-	}
-	g_string_append_printf(str, "\n%s: %s", _("Personal Web Page"), info->personalwebpage);
-	if (info->info && info->info[0]) {
-		g_string_sprintfa(str, "\n%s:\n%s\n%s", _("Additional Information"),
-		                  info->info, _("End of Additional Information"));
-	}
-	g_string_append_c(str, '\n');
-	if ((info->homeaddr &&
-	     (info->homeaddr[0])) ||
-	    (info->homecity &&
-	     info->homecity[0]) || (info->homestate && info->homestate[0]) || (info->homezip && info->homezip[0])) {
-		g_string_append_printf(str, "%s:", _("Home Address"));
-		g_string_append_printf(str, "\n%s: %s", _("Address"), info->homeaddr);
-		g_string_append_printf(str, "\n%s: %s", _("City"), info->homecity);
-		g_string_append_printf(str, "\n%s: %s", _("State"), info->homestate);
-		g_string_append_printf(str, "\n%s: %s", _("Zip Code"), info->homezip);
-		g_string_append_c(str, '\n');
-	}
-	if ((info->workaddr &&
-	     info->workaddr[0]) ||
-	    (info->workcity &&
-	     info->workcity[0]) || (info->workstate && info->workstate[0]) || (info->workzip && info->workzip[0])) {
-		g_string_append_printf(str, "%s:", _("Work Address"));
-		g_string_append_printf(str, "\n%s: %s", _("Address"), info->workaddr);
-		g_string_append_printf(str, "\n%s: %s", _("City"), info->workcity);
-		g_string_append_printf(str, "\n%s: %s", _("State"), info->workstate);
-		g_string_append_printf(str, "\n%s: %s", _("Zip Code"), info->workzip);
-		g_string_append_c(str, '\n');
-	}
-	if ((info->workcompany &&
-	     info->workcompany[0]) ||
-	    (info->workdivision &&
-	     info->workdivision[0]) ||
-	    (info->workposition && info->workposition[0]) || (info->workwebpage && info->workwebpage[0])) {
-		g_string_append_printf(str, "%s:", _("Work Information"));
-		g_string_append_printf(str, "\n%s: %s", _("Company"), info->workcompany);
-		g_string_append_printf(str, "\n%s: %s", _("Division"), info->workdivision);
-		g_string_append_printf(str, "\n%s: %s", _("Position"), info->workposition);
-		if (info->workwebpage && info->workwebpage[0]) {
-			g_string_append_printf(str, "\n%s: %s", _("Web Page"), info->workwebpage);
-		}
-		g_string_append_c(str, '\n');
-	}
-
-	imcb_log(ic, "%s\n%s", _("User Info"), str->str);
-	g_string_free(str, TRUE);
-
-	return 1;
-
-}
-
-static char *oscar_encoding_extract(const char *encoding)
-{
-	char *ret = NULL;
-	char *begin, *end;
-
-	g_return_val_if_fail(encoding != NULL, NULL);
-
-	/* Make sure encoding begins with charset= */
-	if (strncmp(encoding, "text/plain; charset=", 20) &&
-	    strncmp(encoding, "text/aolrtf; charset=", 21) &&
-	    strncmp(encoding, "text/x-aolrtf; charset=", 23)) {
-		return NULL;
-	}
-
-	begin = strchr(encoding, '"');
-	end = strrchr(encoding, '"');
-
-	if ((begin == NULL) || (end == NULL) || (begin >= end)) {
-		return NULL;
-	}
-
-	ret = g_strndup(begin + 1, (end - 1) - begin);
-
-	return ret;
-}
-
-static char *oscar_encoding_to_utf8(char *encoding, char *text, int textlen)
-{
-	char *utf8 = g_new0(char, 8192);
-
-	if ((encoding == NULL) || encoding[0] == '\0') {
-		/*		gaim_debug_info("oscar", "Empty encoding, assuming UTF-8\n");*/
-	} else if (!g_strcasecmp(encoding, "iso-8859-1")) {
-		do_iconv("iso-8859-1", "UTF-8", text, utf8, textlen, 8192);
-	} else if (!g_strcasecmp(encoding, "ISO-8859-1-Windows-3.1-Latin-1")) {
-		do_iconv("Windows-1252", "UTF-8", text, utf8, textlen, 8192);
-	} else if (!g_strcasecmp(encoding, "unicode-2-0")) {
-		do_iconv("UCS-2BE", "UTF-8", text, utf8, textlen, 8192);
-	} else if (g_strcasecmp(encoding, "us-ascii") && strcmp(encoding, "utf-8")) {
-		/*		gaim_debug_warning("oscar", "Unrecognized character encoding \"%s\", "
-		  "attempting to convert to UTF-8 anyway\n", encoding);*/
-		do_iconv(encoding, "UTF-8", text, utf8, textlen, 8192);
-	}
-
-	/*
-	 * If utf8 is still NULL then either the encoding is us-ascii/utf-8 or
-	 * we have been unable to convert the text to utf-8 from the encoding
-	 * that was specified.  So we assume it's UTF-8 and hope for the best.
-	 */
-	if (*utf8 == 0) {
-		strncpy(utf8, text, textlen);
-	}
-
-	return utf8;
-}
-
-static int gaim_parseaiminfo(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	struct im_connection *ic = sess->aux_data;
-	va_list ap;
-	aim_userinfo_t *userinfo;
-	guint16 infotype;
-	char *text_encoding = NULL, *text = NULL, *extracted_encoding = NULL;
-	guint16 text_length;
-	char *utf8 = NULL;
-
-	va_start(ap, fr);
-	userinfo = va_arg(ap, aim_userinfo_t *);
-	infotype = va_arg(ap, int);
-	text_encoding = va_arg(ap, char*);
-	text = va_arg(ap, char*);
-	text_length = va_arg(ap, int);
-	va_end(ap);
-
-	if (text_encoding) {
-		extracted_encoding = oscar_encoding_extract(text_encoding);
-	}
-	if (infotype == AIM_GETINFO_GENERALINFO) {
-		/*Display idle time*/
-		char buff[256];
-		struct tm idletime;
-		if (userinfo->idletime) {
-			memset(&idletime, 0, sizeof(struct tm));
-			idletime.tm_mday = (userinfo->idletime / 60) / 24;
-			idletime.tm_hour = (userinfo->idletime / 60) % 24;
-			idletime.tm_min = userinfo->idletime % 60;
-			idletime.tm_sec = 0;
-			strftime(buff, 256, _("%d days %H hours %M minutes"), &idletime);
-			imcb_log(ic, "%s: %s", _("Idle Time"), buff);
-		}
-
-		if (text) {
-			utf8 = oscar_encoding_to_utf8(extracted_encoding, text, text_length);
-			imcb_log(ic, "%s\n%s", _("User Info"), utf8);
-		} else {
-			imcb_log(ic, _("No user info available."));
-		}
-	} else if (infotype == AIM_GETINFO_AWAYMESSAGE && userinfo->flags & AIM_FLAG_AWAY) {
-		utf8 = oscar_encoding_to_utf8(extracted_encoding, text, text_length);
-		imcb_log(ic, "%s\n%s", _("Away Message"), utf8);
-	}
-
-	g_free(utf8);
-
-	return 1;
-}
-
-int gaim_parsemtn(aim_session_t *sess, aim_frame_t *fr, ...)
-{
-	struct im_connection * ic = sess->aux_data;
-	va_list ap;
-	guint16 type2;
-	char * sn;
-
-	va_start(ap, fr);
-	va_arg(ap, int); /* type1 */
-	sn = va_arg(ap, char*);
-	type2 = va_arg(ap, int);
-	va_end(ap);
-
-	if (type2 == 0x0002) {
-		/* User is typing */
-		imcb_buddy_typing(ic, normalize(sn), OPT_TYPING);
-	} else if (type2 == 0x0001) {
-		/* User has typed something, but is not actively typing (stale) */
-		imcb_buddy_typing(ic, normalize(sn), OPT_THINKING);
-	} else {
-		/* User has stopped typing */
-		imcb_buddy_typing(ic, normalize(sn), 0);
-	}
-
-	return 1;
-}
-
-int oscar_send_typing(struct im_connection *ic, char * who, int typing)
-{
-	struct oscar_data *od = ic->proto_data;
-
-	return(aim_im_sendmtn(od->sess, 1, who, (typing & OPT_TYPING) ? 0x0002 : 0x0000));
-}
-
-void oscar_chat_msg(struct groupchat *c, char *message, int msgflags)
-{
-	struct im_connection *ic = c->ic;
-	struct oscar_data * od = (struct oscar_data*) ic->proto_data;
-	struct chat_connection * ccon;
-	int ret;
-	guint8 len = strlen(message);
-	guint16 flags;
-	char *s;
-
-	if (!(ccon = c->data)) {
-		return;
-	}
-
-	for (s = message; *s; s++) {
-		if (*s & 128) {
-			break;
-		}
-	}
-
-	flags = AIM_CHATFLAGS_NOREFLECT;
-
-	/* Message contains high ASCII chars, time for some translation! */
-	if (*s) {
-		s = g_malloc(BUF_LONG);
-		/* Try if we can put it in an ISO8859-1 string first.
-		   If we can't, fall back to UTF16. */
-		if ((ret = do_iconv("UTF-8", "ISO8859-1", message, s, len, BUF_LONG)) >= 0) {
-			flags |= AIM_CHATFLAGS_ISO_8859_1;
-			len = ret;
-		} else if ((ret = do_iconv("UTF-8", "UCS-2BE", message, s, len, BUF_LONG)) >= 0) {
-			flags |= AIM_CHATFLAGS_UNICODE;
-			len = ret;
-		} else {
-			/* OOF, translation failed... Oh well.. */
-			g_free(s);
-			s = message;
-		}
-	} else {
-		s = message;
-	}
-
-	ret = aim_chat_send_im(od->sess, ccon->conn, flags, s, len);
-
-	if (s != message) {
-		g_free(s);
-	}
-
-/*  return (ret >= 0); */
-}
-
-void oscar_chat_invite(struct groupchat *c, char *who, char *message)
-{
-	struct im_connection *ic = c->ic;
-	struct oscar_data * od = (struct oscar_data *) ic->proto_data;
-	struct chat_connection *ccon;
-
-	if (!(ccon = c->data)) {
-		return;
-	}
-
-	aim_chat_invite(od->sess, od->conn, who, message ? message : "",
-	                ccon->exchange, ccon->name, 0x0);
-}
-
-void oscar_chat_kill(struct im_connection *ic, struct chat_connection *cc)
-{
-	struct oscar_data *od = (struct oscar_data *) ic->proto_data;
-
-	/* Notify the conversation window that we've left the chat */
-	imcb_chat_free(cc->cnv);
-
-	/* Destroy the chat_connection */
-	od->oscar_chats = g_slist_remove(od->oscar_chats, cc);
-	if (cc->inpa > 0) {
-		b_event_remove(cc->inpa);
-		cc->inpa = 0;
-	}
-	aim_conn_kill(od->sess, &cc->conn);
-	g_free(cc->name);
-	g_free(cc->show);
-	g_free(cc);
-}
-
-void oscar_chat_leave(struct groupchat *c)
-{
-	if (!c->data) {
-		return;
-	}
-	oscar_chat_kill(c->ic, c->data);
-}
-
-struct groupchat *oscar_chat_join_internal(struct im_connection *ic, const char *room,
-                                           const char *nick, const char *password, int exchange_number)
-{
-	struct oscar_data * od = (struct oscar_data *) ic->proto_data;
-	struct groupchat *ret = imcb_chat_new(ic, room);
-	aim_conn_t * cur;
-
-	if ((cur = aim_getconn_type(od->sess, AIM_CONN_TYPE_CHATNAV))) {
-		aim_chatnav_createroom(od->sess, cur, room, exchange_number);
-
-		return ret;
-	} else {
-		struct create_room * cr = g_new0(struct create_room, 1);
-
-		cr->exchange = exchange_number;
-		cr->name = g_strdup(room);
-		od->create_rooms = g_slist_append(od->create_rooms, cr);
-		aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_CHATNAV);
-
-		return ret;
-	}
-}
-
-struct groupchat *oscar_chat_join(struct im_connection *ic, const char *room,
-                                  const char *nick, const char *password, set_t **sets)
-{
-	return oscar_chat_join_internal(ic, room, nick, password, set_getint(sets, "exchange_number"));
-}
-
-struct groupchat *oscar_chat_with(struct im_connection * ic, char *who)
-{
-	struct oscar_data * od = (struct oscar_data *) ic->proto_data;
-	struct groupchat *ret;
-	static int chat_id = 0;
-	char * chatname, *s;
-
-	chatname = g_strdup_printf("%s%s%d", g_ascii_isdigit(*ic->acc->user) ? "icq" : "",
-	                           ic->acc->user, chat_id++);
-
-	for (s = chatname; *s; s++) {
-		if (!g_ascii_isalnum(*s)) {
-			*s = '0';
-		}
-	}
-
-	ret = oscar_chat_join_internal(ic, chatname, NULL, NULL, 4);
-	aim_chat_invite(od->sess, od->conn, who, "", 4, chatname, 0x0);
-
-	g_free(chatname);
-
-	return ret;
-}
-
-void oscar_accept_chat(void *data)
-{
-	struct aim_chat_invitation * inv = data;
-
-	oscar_chat_join_internal(inv->ic, inv->name, NULL, NULL, 4);
-	g_free(inv->name);
-	g_free(inv);
-}
-
-void oscar_reject_chat(void *data)
-{
-	struct aim_chat_invitation * inv = data;
-
-	g_free(inv->name);
-	g_free(inv);
-}
-
-void oscar_chat_add_settings(account_t *acc, set_t **head)
-{
-	set_add(head, "exchange_number", "4", set_eval_int, NULL);
-}
-
-void oscar_chat_free_settings(account_t *acc, set_t **head)
-{
-	set_del(head, "exchange_number");
-}
-
-void oscar_initmodule()
-{
-	struct prpl *ret = g_new0(struct prpl, 1);
-
-	ret->name = "oscar";
-	ret->mms = 2343;   /* this guess taken from libotr UPGRADING file */
-	ret->away_states = oscar_away_states;
-	ret->init = oscar_init;
-	ret->login = oscar_login;
-	ret->keepalive = oscar_keepalive;
-	ret->logout = oscar_logout;
-	ret->buddy_msg = oscar_buddy_msg;
-	ret->get_info = oscar_get_info;
-	ret->set_away = oscar_set_away;
-	ret->add_buddy = oscar_add_buddy;
-	ret->remove_buddy = oscar_remove_buddy;
-	ret->chat_msg = oscar_chat_msg;
-	ret->chat_invite = oscar_chat_invite;
-	ret->chat_leave = oscar_chat_leave;
-	ret->chat_with = oscar_chat_with;
-	ret->chat_join = oscar_chat_join;
-	ret->chat_add_settings = oscar_chat_add_settings;
-	ret->chat_free_settings = oscar_chat_free_settings;
-	ret->add_permit = oscar_add_permit;
-	ret->add_deny = oscar_add_deny;
-	ret->rem_permit = oscar_rem_permit;
-	ret->rem_deny = oscar_rem_deny;
-	ret->send_typing = oscar_send_typing;
-
-	ret->handle_cmp = aim_sncmp;
-
-	register_protocol(ret);
-}
Index: protocols/oscar/oscar_util.c
===================================================================
--- protocols/oscar/oscar_util.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,78 +1,0 @@
-#include <aim.h>
-#include <ctype.h>
-
-/*
-* int snlen(const char *)
-*
-* This takes a screen name and returns its length without
-* spaces.  If there are no spaces in the SN, then the
-* return is equal to that of strlen().
-*
-*/
-static int aim_snlen(const char *sn)
-{
-	int i = 0;
-	const char *curPtr = NULL;
-
-	if (!sn) {
-		return 0;
-	}
-
-	curPtr = sn;
-	while ((*curPtr) != (char) '\0') {
-		if ((*curPtr) != ' ') {
-			i++;
-		}
-		curPtr++;
-	}
-
-	return i;
-}
-
-/*
-* int sncmp(const char *, const char *)
-*
-* This takes two screen names and compares them using the rules
-* on screen names for AIM/AOL.  Mainly, this means case and space
-* insensitivity (all case differences and spacing differences are
-* ignored).
-*
-* Return: 0 if equal
-*     non-0 if different
-*
-*/
-
-int aim_sncmp(const char *sn1, const char *sn2)
-{
-	const char *curPtr1 = NULL, *curPtr2 = NULL;
-
-	if (aim_snlen(sn1) != aim_snlen(sn2)) {
-		return 1;
-	}
-
-	curPtr1 = sn1;
-	curPtr2 = sn2;
-	while ((*curPtr1 != (char) '\0') && (*curPtr2 != (char) '\0')) {
-		if ((*curPtr1 == ' ') || (*curPtr2 == ' ')) {
-			if (*curPtr1 == ' ') {
-				curPtr1++;
-			}
-			if (*curPtr2 == ' ') {
-				curPtr2++;
-			}
-		} else {
-			if (g_ascii_toupper(*curPtr1) != g_ascii_toupper(*curPtr2)) {
-				return 1;
-			}
-			curPtr1++;
-			curPtr2++;
-		}
-	}
-
-	/* Should both be NULL */
-	if (*curPtr1 != *curPtr2) {
-		return 1;
-	}
-
-	return 0;
-}
Index: protocols/oscar/rxhandlers.c
===================================================================
--- protocols/oscar/rxhandlers.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,384 +1,0 @@
-/*
- * aim_rxhandlers.c
- *
- * This file contains most all of the incoming packet handlers, along
- * with aim_rxdispatch(), the Rx dispatcher.  Queue/list management is
- * actually done in aim_rxqueue.c.
- *
- */
-
-#include <aim.h>
-
-struct aim_rxcblist_s {
-	guint16 family;
-	guint16 type;
-	aim_rxcallback_t handler;
-	u_short flags;
-	struct aim_rxcblist_s *next;
-};
-
-aim_module_t *aim__findmodulebygroup(aim_session_t *sess, guint16 group)
-{
-	aim_module_t *cur;
-
-	for (cur = (aim_module_t *) sess->modlistv; cur; cur = cur->next) {
-		if (cur->family == group) {
-			return cur;
-		}
-	}
-
-	return NULL;
-}
-
-static aim_module_t *aim__findmodule(aim_session_t *sess, const char *name)
-{
-	aim_module_t *cur;
-
-	for (cur = (aim_module_t *) sess->modlistv; cur; cur = cur->next) {
-		if (strcmp(name, cur->name) == 0) {
-			return cur;
-		}
-	}
-
-	return NULL;
-}
-
-int aim__registermodule(aim_session_t *sess, int (*modfirst)(aim_session_t *, aim_module_t *))
-{
-	aim_module_t *mod;
-
-	if (!sess || !modfirst) {
-		return -1;
-	}
-
-	if (!(mod = g_new0(aim_module_t, 1))) {
-		return -1;
-	}
-
-	if (modfirst(sess, mod) == -1) {
-		g_free(mod);
-		return -1;
-	}
-
-	if (aim__findmodule(sess, mod->name)) {
-		if (mod->shutdown) {
-			mod->shutdown(sess, mod);
-		}
-		g_free(mod);
-		return -1;
-	}
-
-	mod->next = (aim_module_t *) sess->modlistv;
-	sess->modlistv = mod;
-
-
-	return 0;
-}
-
-void aim__shutdownmodules(aim_session_t *sess)
-{
-	aim_module_t *cur;
-
-	for (cur = (aim_module_t *) sess->modlistv; cur; ) {
-		aim_module_t *tmp;
-
-		tmp = cur->next;
-
-		if (cur->shutdown) {
-			cur->shutdown(sess, cur);
-		}
-
-		g_free(cur);
-
-		cur = tmp;
-	}
-
-	sess->modlistv = NULL;
-
-	return;
-}
-
-static int consumesnac(aim_session_t *sess, aim_frame_t *rx)
-{
-	aim_module_t *cur;
-	aim_modsnac_t snac;
-
-	if (aim_bstream_empty(&rx->data) < 10) {
-		return 0;
-	}
-
-	snac.family = aimbs_get16(&rx->data);
-	snac.subtype = aimbs_get16(&rx->data);
-	snac.flags = aimbs_get16(&rx->data);
-	snac.id = aimbs_get32(&rx->data);
-
-	/* Contains TLV(s) in the FNAC header */
-	if (snac.flags & 0x8000) {
-		aim_bstream_advance(&rx->data, aimbs_get16(&rx->data));
-	} else if (snac.flags & 0x0001) {
-		/* Following SNAC will be related */
-	}
-
-	for (cur = (aim_module_t *) sess->modlistv; cur; cur = cur->next) {
-
-		if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) &&
-		    (cur->family != snac.family)) {
-			continue;
-		}
-
-		if (cur->snachandler(sess, cur, rx, &snac, &rx->data)) {
-			return 1;
-		}
-
-	}
-
-	return 0;
-}
-
-static int consumenonsnac(aim_session_t *sess, aim_frame_t *rx, guint16 family, guint16 subtype)
-{
-	aim_module_t *cur;
-	aim_modsnac_t snac;
-
-	snac.family = family;
-	snac.subtype = subtype;
-	snac.flags = snac.id = 0;
-
-	for (cur = (aim_module_t *) sess->modlistv; cur; cur = cur->next) {
-
-		if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) &&
-		    (cur->family != snac.family)) {
-			continue;
-		}
-
-		if (cur->snachandler(sess, cur, rx, &snac, &rx->data)) {
-			return 1;
-		}
-
-	}
-
-	return 0;
-}
-
-static int negchan_middle(aim_session_t *sess, aim_frame_t *fr)
-{
-	aim_tlvlist_t *tlvlist;
-	char *msg = NULL;
-	guint16 code = 0;
-	aim_rxcallback_t userfunc;
-	int ret = 1;
-
-	if (aim_bstream_empty(&fr->data) == 0) {
-		/* XXX should do something with this */
-		return 1;
-	}
-
-	/* Used only by the older login protocol */
-	/* XXX remove this special case? */
-	if (fr->conn->type == AIM_CONN_TYPE_AUTH) {
-		return consumenonsnac(sess, fr, 0x0017, 0x0003);
-	}
-
-	tlvlist = aim_readtlvchain(&fr->data);
-
-	if (aim_gettlv(tlvlist, 0x0009, 1)) {
-		code = aim_gettlv16(tlvlist, 0x0009, 1);
-	}
-
-	if (aim_gettlv(tlvlist, 0x000b, 1)) {
-		msg = aim_gettlv_str(tlvlist, 0x000b, 1);
-	}
-
-	if ((userfunc = aim_callhandler(sess, fr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR))) {
-		ret = userfunc(sess, fr, code, msg);
-	}
-
-	aim_freetlvchain(&tlvlist);
-
-	g_free(msg);
-
-	return ret;
-}
-
-/*
- * Some SNACs we do not allow to be hooked, for good reason.
- */
-static int checkdisallowed(guint16 group, guint16 type)
-{
-	static const struct {
-		guint16 group;
-		guint16 type;
-	} dontuse[] = {
-		{ 0x0001, 0x0002 },
-		{ 0x0001, 0x0003 },
-		{ 0x0001, 0x0006 },
-		{ 0x0001, 0x0007 },
-		{ 0x0001, 0x0008 },
-		{ 0x0001, 0x0017 },
-		{ 0x0001, 0x0018 },
-		{ 0x0000, 0x0000 }
-	};
-	int i;
-
-	for (i = 0; dontuse[i].group != 0x0000; i++) {
-		if ((dontuse[i].group == group) && (dontuse[i].type == type)) {
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-int aim_conn_addhandler(aim_session_t *sess, aim_conn_t *conn, guint16 family, guint16 type,
-                        aim_rxcallback_t newhandler, guint16 flags)
-{
-	struct aim_rxcblist_s *newcb;
-
-	g_return_val_if_fail(conn, -1);
-	g_return_val_if_fail(!checkdisallowed(family, type), -1);
-
-	if (!(newcb = (struct aim_rxcblist_s *) g_new0(struct aim_rxcblist_s, 1))) {
-		return -1;
-	}
-
-	newcb->family = family;
-	newcb->type = type;
-	newcb->flags = flags;
-	newcb->handler = newhandler;
-	newcb->next = NULL;
-
-	if (!conn->handlerlist) {
-		conn->handlerlist = (void *) newcb;
-	} else {
-		struct aim_rxcblist_s *cur;
-
-		for (cur = (struct aim_rxcblist_s *) conn->handlerlist; cur->next; cur = cur->next) {
-			;
-		}
-		cur->next = newcb;
-	}
-
-	return 0;
-}
-
-int aim_clearhandlers(aim_conn_t *conn)
-{
-	struct aim_rxcblist_s *cur;
-
-	if (!conn) {
-		return -1;
-	}
-
-	for (cur = (struct aim_rxcblist_s *) conn->handlerlist; cur; ) {
-		struct aim_rxcblist_s *tmp;
-
-		tmp = cur->next;
-		g_free(cur);
-		cur = tmp;
-	}
-	conn->handlerlist = NULL;
-
-	return 0;
-}
-
-aim_rxcallback_t aim_callhandler(aim_session_t *sess, aim_conn_t *conn, guint16 family, guint16 type)
-{
-	struct aim_rxcblist_s *cur;
-
-	if (!conn) {
-		return NULL;
-	}
-
-	for (cur = (struct aim_rxcblist_s *) conn->handlerlist; cur; cur = cur->next) {
-		if ((cur->family == family) && (cur->type == type)) {
-			return cur->handler;
-		}
-	}
-
-	if (type == AIM_CB_SPECIAL_DEFAULT) {
-		return NULL; /* prevent infinite recursion */
-	}
-
-	return aim_callhandler(sess, conn, family, AIM_CB_SPECIAL_DEFAULT);
-}
-
-static int aim_callhandler_noparam(aim_session_t *sess, aim_conn_t *conn, guint16 family, guint16 type,
-                                   aim_frame_t *ptr)
-{
-	aim_rxcallback_t userfunc;
-
-	if ((userfunc = aim_callhandler(sess, conn, family, type))) {
-		return userfunc(sess, ptr);
-	}
-
-	return 1; /* XXX */
-}
-
-/*
- * aim_rxdispatch()
- *
- * Basically, heres what this should do:
- *   1) Determine correct packet handler for this packet
- *   2) Mark the packet handled (so it can be dequeued in purge_queue())
- *   3) Send the packet to the packet handler
- *   4) Go to next packet in the queue and start over
- *   5) When done, run purge_queue() to purge handled commands
- *
- * TODO: Clean up.
- * TODO: More support for mid-level handlers.
- * TODO: Allow for NULL handlers.
- *
- */
-void aim_rxdispatch(aim_session_t *sess)
-{
-	int i;
-	aim_frame_t *cur;
-
-	for (cur = sess->queue_incoming, i = 0; cur; cur = cur->next, i++) {
-
-		/*
-		 * XXX: This is still fairly ugly.
-		 */
-
-		if (cur->handled) {
-			continue;
-		}
-
-		if (cur->hdr.flap.type == 0x01) {
-
-			cur->handled = aim_callhandler_noparam(sess, cur->conn, AIM_CB_FAM_SPECIAL,
-			                                       AIM_CB_SPECIAL_FLAPVER, cur);                                      /* XXX use consumenonsnac */
-
-			continue;
-
-		} else if (cur->hdr.flap.type == 0x02) {
-
-			if ((cur->handled = consumesnac(sess, cur))) {
-				continue;
-			}
-
-		} else if (cur->hdr.flap.type == 0x04) {
-
-			cur->handled = negchan_middle(sess, cur);
-			continue;
-
-		} else if (cur->hdr.flap.type == 0x05) {
-			;
-		}
-
-		if (!cur->handled) {
-			consumenonsnac(sess, cur, 0xffff, 0xffff); /* last chance! */
-			cur->handled = 1;
-		}
-	}
-
-	/*
-	 * This doesn't have to be called here.  It could easily be done
-	 * by a separate thread or something. It's an administrative operation,
-	 * and can take a while. Though the less you call it the less memory
-	 * you'll have :)
-	 */
-	aim_purge_rxqueue(sess);
-
-	return;
-}
Index: protocols/oscar/rxqueue.c
===================================================================
--- protocols/oscar/rxqueue.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,530 +1,0 @@
-/*
- *  aim_rxqueue.c
- *
- * This file contains the management routines for the receive
- * (incoming packet) queue.  The actual packet handlers are in
- * aim_rxhandlers.c.
- */
-
-#include <aim.h>
-
-#include <sys/socket.h>
-
-/*
- *
- */
-int aim_recv(int fd, void *buf, size_t count)
-{
-	int left, cur;
-
-	for (cur = 0, left = count; left; ) {
-		int ret;
-
-		ret = recv(fd, ((unsigned char *) buf) + cur, left, 0);
-
-		/* Of course EOF is an error, only morons disagree with that. */
-		if (ret <= 0) {
-			return -1;
-		}
-
-		cur += ret;
-		left -= ret;
-	}
-
-	return cur;
-}
-
-/*
- * Read into a byte stream.  Will not read more than count, but may read
- * less if there is not enough room in the stream buffer.
- */
-static int aim_bstream_recv(aim_bstream_t *bs, int fd, size_t count)
-{
-	int red = 0;
-
-	if (!bs || (fd < 0) || (count < 0)) {
-		return -1;
-	}
-
-	if (count > (bs->len - bs->offset)) {
-		count = bs->len - bs->offset; /* truncate to remaining space */
-
-	}
-	if (count) {
-
-		red = aim_recv(fd, bs->data + bs->offset, count);
-
-		if (red <= 0) {
-			return -1;
-		}
-	}
-
-	bs->offset += red;
-
-	return red;
-}
-
-int aim_bstream_init(aim_bstream_t *bs, guint8 *data, int len)
-{
-
-	if (!bs) {
-		return -1;
-	}
-
-	bs->data = data;
-	bs->len = len;
-	bs->offset = 0;
-
-	return 0;
-}
-
-int aim_bstream_empty(aim_bstream_t *bs)
-{
-	return bs->len - bs->offset;
-}
-
-int aim_bstream_curpos(aim_bstream_t *bs)
-{
-	return bs->offset;
-}
-
-int aim_bstream_setpos(aim_bstream_t *bs, int off)
-{
-
-	if (off > bs->len) {
-		return -1;
-	}
-
-	bs->offset = off;
-
-	return off;
-}
-
-void aim_bstream_rewind(aim_bstream_t *bs)
-{
-
-	aim_bstream_setpos(bs, 0);
-
-	return;
-}
-
-int aim_bstream_advance(aim_bstream_t *bs, int n)
-{
-
-	if (aim_bstream_empty(bs) < n) {
-		return 0; /* XXX throw an exception */
-
-	}
-	bs->offset += n;
-
-	return n;
-}
-
-guint8 aimbs_get8(aim_bstream_t *bs)
-{
-
-	if (aim_bstream_empty(bs) < 1) {
-		return 0; /* XXX throw an exception */
-
-	}
-	bs->offset++;
-
-	return aimutil_get8(bs->data + bs->offset - 1);
-}
-
-guint16 aimbs_get16(aim_bstream_t *bs)
-{
-
-	if (aim_bstream_empty(bs) < 2) {
-		return 0; /* XXX throw an exception */
-
-	}
-	bs->offset += 2;
-
-	return aimutil_get16(bs->data + bs->offset - 2);
-}
-
-guint32 aimbs_get32(aim_bstream_t *bs)
-{
-
-	if (aim_bstream_empty(bs) < 4) {
-		return 0; /* XXX throw an exception */
-
-	}
-	bs->offset += 4;
-
-	return aimutil_get32(bs->data + bs->offset - 4);
-}
-
-guint8 aimbs_getle8(aim_bstream_t *bs)
-{
-
-	if (aim_bstream_empty(bs) < 1) {
-		return 0; /* XXX throw an exception */
-
-	}
-	bs->offset++;
-
-	return aimutil_getle8(bs->data + bs->offset - 1);
-}
-
-guint16 aimbs_getle16(aim_bstream_t *bs)
-{
-
-	if (aim_bstream_empty(bs) < 2) {
-		return 0; /* XXX throw an exception */
-
-	}
-	bs->offset += 2;
-
-	return aimutil_getle16(bs->data + bs->offset - 2);
-}
-
-guint32 aimbs_getle32(aim_bstream_t *bs)
-{
-
-	if (aim_bstream_empty(bs) < 4) {
-		return 0; /* XXX throw an exception */
-
-	}
-	bs->offset += 4;
-
-	return aimutil_getle32(bs->data + bs->offset - 4);
-}
-
-int aimbs_put8(aim_bstream_t *bs, guint8 v)
-{
-
-	if (aim_bstream_empty(bs) < 1) {
-		return 0; /* XXX throw an exception */
-
-	}
-	bs->offset += aimutil_put8(bs->data + bs->offset, v);
-
-	return 1;
-}
-
-int aimbs_put16(aim_bstream_t *bs, guint16 v)
-{
-
-	if (aim_bstream_empty(bs) < 2) {
-		return 0; /* XXX throw an exception */
-
-	}
-	bs->offset += aimutil_put16(bs->data + bs->offset, v);
-
-	return 2;
-}
-
-int aimbs_put32(aim_bstream_t *bs, guint32 v)
-{
-
-	if (aim_bstream_empty(bs) < 4) {
-		return 0; /* XXX throw an exception */
-
-	}
-	bs->offset += aimutil_put32(bs->data + bs->offset, v);
-
-	return 1;
-}
-
-int aimbs_putle8(aim_bstream_t *bs, guint8 v)
-{
-
-	if (aim_bstream_empty(bs) < 1) {
-		return 0; /* XXX throw an exception */
-
-	}
-	bs->offset += aimutil_putle8(bs->data + bs->offset, v);
-
-	return 1;
-}
-
-int aimbs_putle16(aim_bstream_t *bs, guint16 v)
-{
-
-	if (aim_bstream_empty(bs) < 2) {
-		return 0; /* XXX throw an exception */
-
-	}
-	bs->offset += aimutil_putle16(bs->data + bs->offset, v);
-
-	return 2;
-}
-
-int aimbs_putle32(aim_bstream_t *bs, guint32 v)
-{
-
-	if (aim_bstream_empty(bs) < 4) {
-		return 0; /* XXX throw an exception */
-
-	}
-	bs->offset += aimutil_putle32(bs->data + bs->offset, v);
-
-	return 1;
-}
-
-int aimbs_getrawbuf(aim_bstream_t *bs, guint8 *buf, int len)
-{
-
-	if (aim_bstream_empty(bs) < len) {
-		return 0;
-	}
-
-	memcpy(buf, bs->data + bs->offset, len);
-	bs->offset += len;
-
-	return len;
-}
-
-guint8 *aimbs_getraw(aim_bstream_t *bs, int len)
-{
-	guint8 *ob;
-
-	if (!(ob = g_malloc(len))) {
-		return NULL;
-	}
-
-	if (aimbs_getrawbuf(bs, ob, len) < len) {
-		g_free(ob);
-		return NULL;
-	}
-
-	return ob;
-}
-
-char *aimbs_getstr(aim_bstream_t *bs, int len)
-{
-	guint8 *ob;
-
-	if (!(ob = g_malloc(len + 1))) {
-		return NULL;
-	}
-
-	if (aimbs_getrawbuf(bs, ob, len) < len) {
-		g_free(ob);
-		return NULL;
-	}
-
-	ob[len] = '\0';
-
-	return (char *) ob;
-}
-
-int aimbs_putraw(aim_bstream_t *bs, const guint8 *v, int len)
-{
-
-	if (aim_bstream_empty(bs) < len) {
-		return 0; /* XXX throw an exception */
-
-	}
-	memcpy(bs->data + bs->offset, v, len);
-	bs->offset += len;
-
-	return len;
-}
-
-int aimbs_putbs(aim_bstream_t *bs, aim_bstream_t *srcbs, int len)
-{
-
-	if (aim_bstream_empty(srcbs) < len) {
-		return 0; /* XXX throw exception (underrun) */
-
-	}
-	if (aim_bstream_empty(bs) < len) {
-		return 0; /* XXX throw exception (overflow) */
-
-	}
-	memcpy(bs->data + bs->offset, srcbs->data + srcbs->offset, len);
-	bs->offset += len;
-	srcbs->offset += len;
-
-	return len;
-}
-
-/**
- * aim_frame_destroy - free aim_frame_t
- * @frame: the frame to free
- *
- * returns -1 on error; 0 on success.
- *
- */
-void aim_frame_destroy(aim_frame_t *frame)
-{
-
-	g_free(frame->data.data); /* XXX aim_bstream_free */
-
-	g_free(frame);
-}
-
-
-/*
- * Grab a single command sequence off the socket, and enqueue
- * it in the incoming event queue in a separate struct.
- */
-int aim_get_command(aim_session_t *sess, aim_conn_t *conn)
-{
-	guint8 flaphdr_raw[6];
-	aim_bstream_t flaphdr;
-	aim_frame_t *newrx;
-	guint16 payloadlen;
-
-	if (!sess || !conn) {
-		return 0;
-	}
-
-	if (conn->fd == -1) {
-		return -1; /* its a aim_conn_close()'d connection */
-
-	}
-	/* KIDS, THIS IS WHAT HAPPENS IF YOU USE CODE WRITTEN FOR GUIS IN A DAEMON!
-
-	   And wouldn't it make sense to return something that prevents this function
-	   from being called again IMMEDIATELY (and making the program suck up all
-	   CPU time)?...
-
-	if (conn->fd < 3)
-	        return 0;
-	*/
-
-	if (conn->status & AIM_CONN_STATUS_INPROGRESS) {
-		return aim_conn_completeconnect(sess, conn);
-	}
-
-	aim_bstream_init(&flaphdr, flaphdr_raw, sizeof(flaphdr_raw));
-
-	/*
-	 * Read FLAP header.  Six bytes:
-	 *
-	 *   0 char  -- Always 0x2a
-	 *   1 char  -- Channel ID.  Usually 2 -- 1 and 4 are used during login.
-	 *   2 short -- Sequence number
-	 *   4 short -- Number of data bytes that follow.
-	 */
-	if (aim_bstream_recv(&flaphdr, conn->fd, 6) < 6) {
-		aim_conn_close(conn);
-		return -1;
-	}
-
-	aim_bstream_rewind(&flaphdr);
-
-	/*
-	 * This shouldn't happen unless the socket breaks, the server breaks,
-	 * or we break.  We must handle it just in case.
-	 */
-	if (aimbs_get8(&flaphdr) != 0x2a) {
-		aim_bstream_rewind(&flaphdr);
-		aimbs_get8(&flaphdr);
-		imcb_error(sess->aux_data, "FLAP framing disrupted");
-		aim_conn_close(conn);
-		return -1;
-	}
-
-	/* allocate a new struct */
-	if (!(newrx = (aim_frame_t *) g_new0(aim_frame_t, 1))) {
-		return -1;
-	}
-
-	/* we're doing FLAP if we're here */
-	newrx->hdrtype = AIM_FRAMETYPE_FLAP;
-
-	newrx->hdr.flap.type = aimbs_get8(&flaphdr);
-	newrx->hdr.flap.seqnum = aimbs_get16(&flaphdr);
-	payloadlen = aimbs_get16(&flaphdr);
-
-	newrx->nofree = 0; /* free by default */
-
-	if (payloadlen) {
-		guint8 *payload = NULL;
-
-		if (!(payload = (guint8 *) g_malloc(payloadlen))) {
-			aim_frame_destroy(newrx);
-			return -1;
-		}
-
-		aim_bstream_init(&newrx->data, payload, payloadlen);
-
-		/* read the payload */
-		if (aim_bstream_recv(&newrx->data, conn->fd, payloadlen) < payloadlen) {
-			aim_frame_destroy(newrx); /* free's payload */
-			aim_conn_close(conn);
-			return -1;
-		}
-	} else {
-		aim_bstream_init(&newrx->data, NULL, 0);
-	}
-
-
-	aim_bstream_rewind(&newrx->data);
-
-	newrx->conn = conn;
-
-	newrx->next = NULL;  /* this will always be at the bottom */
-
-	if (!sess->queue_incoming) {
-		sess->queue_incoming = newrx;
-	} else {
-		aim_frame_t *cur;
-
-		for (cur = sess->queue_incoming; cur->next; cur = cur->next) {
-			;
-		}
-		cur->next = newrx;
-	}
-
-	newrx->conn->lastactivity = time(NULL);
-
-	return 0;
-}
-
-/*
- * Purge receive queue of all handled commands (->handled==1).  Also
- * allows for selective freeing using ->nofree so that the client can
- * keep the data for various purposes.
- *
- * If ->nofree is nonzero, the frame will be delinked from the global list,
- * but will not be free'ed.  The client _must_ keep a pointer to the
- * data -- libfaim will not!  If the client marks ->nofree but
- * does not keep a pointer, it's lost forever.
- *
- */
-void aim_purge_rxqueue(aim_session_t *sess)
-{
-	aim_frame_t *cur, **prev;
-
-	for (prev = &sess->queue_incoming; (cur = *prev); ) {
-		if (cur->handled) {
-
-			*prev = cur->next;
-
-			if (!cur->nofree) {
-				aim_frame_destroy(cur);
-			}
-
-		} else {
-			prev = &cur->next;
-		}
-	}
-
-	return;
-}
-
-/*
- * Since aim_get_command will aim_conn_kill dead connections, we need
- * to clean up the rxqueue of unprocessed connections on that socket.
- *
- * XXX: this is something that was handled better in the old connection
- * handling method, but eh.
- */
-void aim_rxqueue_cleanbyconn(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_frame_t *currx;
-
-	for (currx = sess->queue_incoming; currx; currx = currx->next) {
-		if ((!currx->handled) && (currx->conn == conn)) {
-			currx->handled = 1;
-		}
-	}
-	return;
-}
-
Index: protocols/oscar/search.c
===================================================================
--- protocols/oscar/search.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,106 +1,0 @@
-
-/*
- * aim_search.c
- *
- * TODO: Add aim_usersearch_name()
- *
- */
-
-#include <aim.h>
-
-/* XXX can this be integrated with the rest of the error handling? */
-static int error(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	aim_snac_t *snac2;
-
-	/* XXX the modules interface should have already retrieved this for us */
-	if (!(snac2 = aim_remsnac(sess, snac->id))) {
-		imcb_error(sess->aux_data, "couldn't get snac");
-		return 0;
-	}
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, snac2->data /* address */);
-	}
-
-	/* XXX freesnac()? */
-	if (snac2) {
-		g_free(snac2->data);
-	}
-	g_free(snac2);
-
-	return ret;
-}
-
-static int reply(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int j = 0, m, ret = 0;
-	aim_tlvlist_t *tlvlist;
-	char *cur = NULL, *buf = NULL;
-	aim_rxcallback_t userfunc;
-	aim_snac_t *snac2;
-	char *searchaddr = NULL;
-
-	if ((snac2 = aim_remsnac(sess, snac->id))) {
-		searchaddr = (char *) snac2->data;
-	}
-
-	tlvlist = aim_readtlvchain(bs);
-	m = aim_counttlvchain(&tlvlist);
-
-	/* XXX uhm. */
-	while ((cur = aim_gettlv_str(tlvlist, 0x0001, j + 1)) && j < m) {
-		buf = g_realloc(buf, (j + 1) * (MAXSNLEN + 1));
-
-		strncpy(&buf[j * (MAXSNLEN + 1)], cur, MAXSNLEN);
-		g_free(cur);
-
-		j++;
-	}
-
-	aim_freetlvchain(&tlvlist);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, searchaddr, j, buf);
-	}
-
-	/* XXX freesnac()? */
-	if (snac2) {
-		g_free(snac2->data);
-	}
-	g_free(snac2);
-
-	g_free(buf);
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0001) {
-		return error(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == 0x0003) {
-		return reply(sess, mod, rx, snac, bs);
-	}
-
-	return 0;
-}
-
-int search_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x000a;
-	mod->version = 0x0001;
-	mod->toolid = 0x0110;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "search", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
-
-
Index: protocols/oscar/search.h
===================================================================
--- protocols/oscar/search.h	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,4 +1,0 @@
-#ifndef __OSCAR_SEARCH_H__
-#define __OSCAR_SEARCH_H__
-
-#endif /* __OSCAR_SEARCH_H__ */
Index: protocols/oscar/service.c
===================================================================
--- protocols/oscar/service.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,806 +1,0 @@
-/*
- * Group 1.  This is a very special group.  All connections support
- * this group, as it does some particularly good things (like rate limiting).
- */
-
-#include <aim.h>
-
-#include "md5.h"
-
-/* Client Online (group 1, subtype 2) */
-int aim_clientready(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_conn_inside_t *ins = (aim_conn_inside_t *) conn->inside;
-	struct snacgroup *sg;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!ins) {
-		return -EINVAL;
-	}
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, 0x0001, 0x0002, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0001, 0x0002, 0x0000, snacid);
-
-	/*
-	 * Send only the tool versions that the server cares about (that it
-	 * marked as supporting in the server ready SNAC).
-	 */
-	for (sg = ins->groups; sg; sg = sg->next) {
-		aim_module_t *mod;
-
-		if ((mod = aim__findmodulebygroup(sess, sg->group))) {
-			aimbs_put16(&fr->data, mod->family);
-			aimbs_put16(&fr->data, mod->version);
-			aimbs_put16(&fr->data, mod->toolid);
-			aimbs_put16(&fr->data, mod->toolversion);
-		}
-	}
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Host Online (group 1, type 3)
- *
- * See comments in conn.c about how the group associations are supposed
- * to work, and how they really work.
- *
- * This info probably doesn't even need to make it to the client.
- *
- * We don't actually call the client here.  This starts off the connection
- * initialization routine required by all AIM connections.  The next time
- * the client is called is the CONNINITDONE callback, which should be
- * shortly after the rate information is acknowledged.
- *
- */
-static int hostonline(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	guint16 *families;
-	int famcount;
-
-
-	if (!(families = g_malloc(aim_bstream_empty(bs)))) {
-		return 0;
-	}
-
-	for (famcount = 0; aim_bstream_empty(bs); famcount++) {
-		families[famcount] = aimbs_get16(bs);
-		aim_conn_addgroup(rx->conn, families[famcount]);
-	}
-
-	g_free(families);
-
-
-	/*
-	 * Next step is in the Host Versions handler.
-	 *
-	 * Note that we must send this before we request rates, since
-	 * the format of the rate information depends on the versions we
-	 * give it.
-	 *
-	 */
-	aim_setversions(sess, rx->conn);
-
-	return 1;
-}
-
-/* Service request (group 1, type 4) */
-int aim_reqservice(aim_session_t *sess, aim_conn_t *conn, guint16 serviceid)
-{
-	return aim_genericreq_s(sess, conn, 0x0001, 0x0004, &serviceid);
-}
-
-/* Redirect (group 1, type 5) */
-static int redirect(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	struct aim_redirect_data redir;
-	aim_rxcallback_t userfunc;
-	aim_tlvlist_t *tlvlist;
-	aim_snac_t *origsnac = NULL;
-	int ret = 0;
-
-	memset(&redir, 0, sizeof(redir));
-
-	tlvlist = aim_readtlvchain(bs);
-
-	if (!aim_gettlv(tlvlist, 0x000d, 1) ||
-	    !aim_gettlv(tlvlist, 0x0005, 1) ||
-	    !aim_gettlv(tlvlist, 0x0006, 1)) {
-		aim_freetlvchain(&tlvlist);
-		return 0;
-	}
-
-	redir.group = aim_gettlv16(tlvlist, 0x000d, 1);
-	redir.ip = aim_gettlv_str(tlvlist, 0x0005, 1);
-	redir.cookie = (guint8 *) aim_gettlv_str(tlvlist, 0x0006, 1);
-
-	/* Fetch original SNAC so we can get csi if needed */
-	origsnac = aim_remsnac(sess, snac->id);
-
-	if ((redir.group == AIM_CONN_TYPE_CHAT) && origsnac) {
-		struct chatsnacinfo *csi = (struct chatsnacinfo *) origsnac->data;
-
-		redir.chat.exchange = csi->exchange;
-		redir.chat.room = csi->name;
-		redir.chat.instance = csi->instance;
-	}
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, &redir);
-	}
-
-	g_free((void *) redir.ip);
-	g_free((void *) redir.cookie);
-
-	if (origsnac) {
-		g_free(origsnac->data);
-	}
-	g_free(origsnac);
-
-	aim_freetlvchain(&tlvlist);
-
-	return ret;
-}
-
-/* Request Rate Information. (group 1, type 6) */
-int aim_reqrates(aim_session_t *sess, aim_conn_t *conn)
-{
-	return aim_genericreq_n(sess, conn, 0x0001, 0x0006);
-}
-
-/*
- * OSCAR defines several 'rate classes'.  Each class has separate
- * rate limiting properties (limit level, alert level, disconnect
- * level, etc), and a set of SNAC family/type pairs associated with
- * it.  The rate classes, their limiting properties, and the definitions
- * of which SNACs are belong to which class, are defined in the
- * Rate Response packet at login to each host.
- *
- * Logically, all rate offenses within one class count against further
- * offenses for other SNACs in the same class (ie, sending messages
- * too fast will limit the number of user info requests you can send,
- * since those two SNACs are in the same rate class).
- *
- * Since the rate classes are defined dynamically at login, the values
- * below may change. But they seem to be fairly constant.
- *
- * Currently, BOS defines five rate classes, with the commonly used
- * members as follows...
- *
- *  Rate class 0x0001:
- *      - Everything thats not in any of the other classes
- *
- *  Rate class 0x0002:
- *      - Buddy list add/remove
- *	- Permit list add/remove
- *	- Deny list add/remove
- *
- *  Rate class 0x0003:
- *	- User information requests
- *	- Outgoing ICBMs
- *
- *  Rate class 0x0004:
- *	- A few unknowns: 2/9, 2/b, and f/2
- *
- *  Rate class 0x0005:
- *	- Chat room create
- *	- Outgoing chat ICBMs
- *
- * The only other thing of note is that class 5 (chat) has slightly looser
- * limiting properties than class 3 (normal messages).  But thats just a
- * small bit of trivia for you.
- *
- * The last thing that needs to be learned about the rate limiting
- * system is how the actual numbers relate to the passing of time.  This
- * seems to be a big mystery.
- *
- */
-
-static void rc_addclass(struct rateclass **head, struct rateclass *inrc)
-{
-	struct rateclass *rc, *rc2;
-
-	if (!(rc = g_malloc(sizeof(struct rateclass)))) {
-		return;
-	}
-
-	memcpy(rc, inrc, sizeof(struct rateclass));
-	rc->next = NULL;
-
-	for (rc2 = *head; rc2 && rc2->next; rc2 = rc2->next) {
-		;
-	}
-
-	if (!rc2) {
-		*head = rc;
-	} else {
-		rc2->next = rc;
-	}
-
-	return;
-}
-
-static struct rateclass *rc_findclass(struct rateclass **head, guint16 id)
-{
-	struct rateclass *rc;
-
-	for (rc = *head; rc; rc = rc->next) {
-		if (rc->classid == id) {
-			return rc;
-		}
-	}
-
-	return NULL;
-}
-
-static void rc_addpair(struct rateclass *rc, guint16 group, guint16 type)
-{
-	struct snacpair *sp, *sp2;
-
-	if (!(sp = g_new0(struct snacpair, 1))) {
-		return;
-	}
-
-	sp->group = group;
-	sp->subtype = type;
-	sp->next = NULL;
-
-	for (sp2 = rc->members; sp2 && sp2->next; sp2 = sp2->next) {
-		;
-	}
-
-	if (!sp2) {
-		rc->members = sp;
-	} else {
-		sp2->next = sp;
-	}
-
-	return;
-}
-
-/* Rate Parameters (group 1, type 7) */
-static int rateresp(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_conn_inside_t *ins = (aim_conn_inside_t *) rx->conn->inside;
-	guint16 numclasses, i;
-	aim_rxcallback_t userfunc;
-
-
-	/*
-	 * First are the parameters for each rate class.
-	 */
-	numclasses = aimbs_get16(bs);
-	for (i = 0; i < numclasses; i++) {
-		struct rateclass rc;
-
-		memset(&rc, 0, sizeof(struct rateclass));
-
-		rc.classid = aimbs_get16(bs);
-		rc.windowsize = aimbs_get32(bs);
-		rc.clear = aimbs_get32(bs);
-		rc.alert = aimbs_get32(bs);
-		rc.limit = aimbs_get32(bs);
-		rc.disconnect = aimbs_get32(bs);
-		rc.current = aimbs_get32(bs);
-		rc.max = aimbs_get32(bs);
-
-		/*
-		 * The server will send an extra five bytes of parameters
-		 * depending on the version we advertised in 1/17.  If we
-		 * didn't send 1/17 (evil!), then this will crash and you
-		 * die, as it will default to the old version but we have
-		 * the new version hardcoded here.
-		 */
-		if (mod->version >= 3) {
-			aimbs_getrawbuf(bs, rc.unknown, sizeof(rc.unknown));
-		}
-
-		rc_addclass(&ins->rates, &rc);
-	}
-
-	/*
-	 * Then the members of each class.
-	 */
-	for (i = 0; i < numclasses; i++) {
-		guint16 classid, count;
-		struct rateclass *rc;
-		int j;
-
-		classid = aimbs_get16(bs);
-		count = aimbs_get16(bs);
-
-		rc = rc_findclass(&ins->rates, classid);
-
-		for (j = 0; j < count; j++) {
-			guint16 group, subtype;
-
-			group = aimbs_get16(bs);
-			subtype = aimbs_get16(bs);
-
-			if (rc) {
-				rc_addpair(rc, group, subtype);
-			}
-		}
-	}
-
-	/*
-	 * We don't pass the rate information up to the client, as it really
-	 * doesn't care.  The information is stored in the connection, however
-	 * so that we can do more fun stuff later (not really).
-	 */
-
-	/*
-	 * Last step in the conn init procedure is to acknowledge that we
-	 * agree to these draconian limitations.
-	 */
-	aim_rates_addparam(sess, rx->conn);
-
-	/*
-	 * Finally, tell the client it's ready to go...
-	 */
-	if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE))) {
-		userfunc(sess, rx);
-	}
-
-
-	return 1;
-}
-
-/* Add Rate Parameter (group 1, type 8) */
-int aim_rates_addparam(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_conn_inside_t *ins = (aim_conn_inside_t *) conn->inside;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	struct rateclass *rc;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 512))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, 0x0001, 0x0008, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0001, 0x0008, 0x0000, snacid);
-
-	for (rc = ins->rates; rc; rc = rc->next) {
-		aimbs_put16(&fr->data, rc->classid);
-	}
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/* Rate Change (group 1, type 0x0a) */
-static int ratechange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_rxcallback_t userfunc;
-	guint16 code, rateclass;
-	guint32 currentavg, maxavg, windowsize, clear, alert, limit, disconnect;
-
-	code = aimbs_get16(bs);
-	rateclass = aimbs_get16(bs);
-
-	windowsize = aimbs_get32(bs);
-	clear = aimbs_get32(bs);
-	alert = aimbs_get32(bs);
-	limit = aimbs_get32(bs);
-	disconnect = aimbs_get32(bs);
-	currentavg = aimbs_get32(bs);
-	maxavg = aimbs_get32(bs);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		return userfunc(sess, rx, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg,
-		                maxavg);
-	}
-
-	return 0;
-}
-
-/*
- * How Migrations work.
- *
- * The server sends a Server Pause message, which the client should respond to
- * with a Server Pause Ack, which contains the families it needs on this
- * connection. The server will send a Migration Notice with an IP address, and
- * then disconnect. Next the client should open the connection and send the
- * cookie.  Repeat the normal login process and pretend this never happened.
- *
- * The Server Pause contains no data.
- *
- */
-
-/* Service Pause (group 1, type 0x0b) */
-static int serverpause(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_rxcallback_t userfunc;
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		return userfunc(sess, rx);
-	}
-
-	return 0;
-}
-
-/* Service Resume (group 1, type 0x0d) */
-static int serverresume(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_rxcallback_t userfunc;
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		return userfunc(sess, rx);
-	}
-
-	return 0;
-}
-
-/* Request self-info (group 1, type 0x0e) */
-int aim_reqpersonalinfo(aim_session_t *sess, aim_conn_t *conn)
-{
-	return aim_genericreq_n(sess, conn, 0x0001, 0x000e);
-}
-
-/* Self User Info (group 1, type 0x0f) */
-static int selfinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_rxcallback_t userfunc;
-	aim_userinfo_t userinfo;
-
-	aim_extractuserinfo(sess, bs, &userinfo);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		return userfunc(sess, rx, &userinfo);
-	}
-
-	return 0;
-}
-
-/* Evil Notification (group 1, type 0x10) */
-static int evilnotify(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_rxcallback_t userfunc;
-	guint16 newevil;
-	aim_userinfo_t userinfo;
-
-	memset(&userinfo, 0, sizeof(aim_userinfo_t));
-
-	newevil = aimbs_get16(bs);
-
-	if (aim_bstream_empty(bs)) {
-		aim_extractuserinfo(sess, bs, &userinfo);
-	}
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		return userfunc(sess, rx, newevil, &userinfo);
-	}
-
-	return 0;
-}
-
-/*
- * Service Migrate (group 1, type 0x12)
- *
- * This is the final SNAC sent on the original connection during a migration.
- * It contains the IP and cookie used to connect to the new server, and
- * optionally a list of the SNAC groups being migrated.
- *
- */
-static int migrate(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_rxcallback_t userfunc;
-	int ret = 0;
-	guint16 groupcount, i;
-	aim_tlvlist_t *tl;
-	char *ip = NULL;
-	aim_tlv_t *cktlv;
-
-	/*
-	 * Apparently there's some fun stuff that can happen right here. The
-	 * migration can actually be quite selective about what groups it
-	 * moves to the new server.  When not all the groups for a connection
-	 * are migrated, or they are all migrated but some groups are moved
-	 * to a different server than others, it is called a bifurcated
-	 * migration.
-	 *
-	 * Let's play dumb and not support that.
-	 *
-	 */
-	groupcount = aimbs_get16(bs);
-	for (i = 0; i < groupcount; i++) {
-		aimbs_get16(bs);
-
-		imcb_error(sess->aux_data, "bifurcated migration unsupported");
-	}
-
-	tl = aim_readtlvchain(bs);
-
-	if (aim_gettlv(tl, 0x0005, 1)) {
-		ip = aim_gettlv_str(tl, 0x0005, 1);
-	}
-
-	cktlv = aim_gettlv(tl, 0x0006, 1);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, ip, cktlv ? cktlv->value : NULL);
-	}
-
-	aim_freetlvchain(&tl);
-	g_free(ip);
-
-	return ret;
-}
-
-/* Message of the Day (group 1, type 0x13) */
-static int motd(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_rxcallback_t userfunc;
-	char *msg = NULL;
-	int ret = 0;
-	aim_tlvlist_t *tlvlist;
-	guint16 id;
-
-	/*
-	 * Code.
-	 *
-	 * Valid values:
-	 *   1 Mandatory upgrade
-	 *   2 Advisory upgrade
-	 *   3 System bulletin
-	 *   4 Nothing's wrong ("top o the world" -- normal)
-	 *   5 Lets-break-something.
-	 *
-	 */
-	id = aimbs_get16(bs);
-
-	/*
-	 * TLVs follow
-	 */
-	tlvlist = aim_readtlvchain(bs);
-
-	msg = aim_gettlv_str(tlvlist, 0x000b, 1);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, id, msg);
-	}
-
-	g_free(msg);
-
-	aim_freetlvchain(&tlvlist);
-
-	return ret;
-}
-
-/*
- * Set privacy flags (group 1, type 0x14)
- *
- * Normally 0x03.
- *
- *  Bit 1:  Allows other AIM users to see how long you've been idle.
- *  Bit 2:  Allows other AIM users to see how long you've been a member.
- *
- */
-int aim_bos_setprivacyflags(aim_session_t *sess, aim_conn_t *conn, guint32 flags)
-{
-	return aim_genericreq_l(sess, conn, 0x0001, 0x0014, &flags);
-}
-
-
-/*
- * Set client versions (group 1, subtype 0x17)
- *
- * If you've seen the clientonline/clientready SNAC you're probably
- * wondering what the point of this one is.  And that point seems to be
- * that the versions in the client online SNAC are sent too late for the
- * server to be able to use them to change the protocol for the earlier
- * login packets (client versions are sent right after Host Online is
- * received, but client online versions aren't sent until quite a bit later).
- * We can see them already making use of this by changing the format of
- * the rate information based on what version of group 1 we advertise here.
- *
- */
-int aim_setversions(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_conn_inside_t *ins = (aim_conn_inside_t *) conn->inside;
-	struct snacgroup *sg;
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!ins) {
-		return -EINVAL;
-	}
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, 0x0001, 0x0017, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0001, 0x0017, 0x0000, snacid);
-
-	/*
-	 * Send only the versions that the server cares about (that it
-	 * marked as supporting in the server ready SNAC).
-	 */
-	for (sg = ins->groups; sg; sg = sg->next) {
-		aim_module_t *mod;
-
-		if ((mod = aim__findmodulebygroup(sess, sg->group))) {
-			aimbs_put16(&fr->data, mod->family);
-			aimbs_put16(&fr->data, mod->version);
-		}
-	}
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/* Host versions (group 1, subtype 0x18) */
-static int hostversions(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	guint8 *versions;
-
-	/* This is frivolous. (Thank you SmarterChild.) */
-	aim_bstream_empty(bs); /* == vercount * 4 */
-	versions = aimbs_getraw(bs, aim_bstream_empty(bs));
-	g_free(versions);
-
-	/*
-	 * Now request rates.
-	 */
-	aim_reqrates(sess, rx->conn);
-
-	return 1;
-}
-
-/*
- * Subtype 0x001e - Extended Status
- *
- * Sets your ICQ status (available, away, do not disturb, etc.)
- *
- * These are the same TLVs seen in user info.  You can
- * also set 0x0008 and 0x000c.
- */
-int aim_setextstatus(aim_session_t *sess, aim_conn_t *conn, guint32 status)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
-	guint32 data;
-	struct im_connection *ic = sess ? sess->aux_data : NULL;
-
-	data = AIM_ICQ_STATE_HIDEIP | status; /* yay for error checking ;^) */
-
-	if (ic && set_getbool(&ic->acc->set, "web_aware")) {
-		data |= AIM_ICQ_STATE_WEBAWARE;
-	}
-
-	aim_addtlvtochain32(&tl, 0x0006, data); /* tlvlen */
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 8))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, 0x0001, 0x001e, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, 0x0001, 0x001e, 0x0000, snacid);
-
-	aim_writetlvchain(&fr->data, &tl);
-	aim_freetlvchain(&tl);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * Starting this past week (26 Mar 2001, say), AOL has started sending
- * this nice little extra SNAC.  AFAIK, it has never been used until now.
- *
- * The request contains eight bytes.  The first four are an offset, the
- * second four are a length.
- *
- * The offset is an offset into aim.exe when it is mapped during execution
- * on Win32.  So far, AOL has only been requesting bytes in static regions
- * of memory.  (I won't put it past them to start requesting data in
- * less static regions -- regions that are initialized at run time, but still
- * before the client receives this request.)
- *
- * When the client receives the request, it adds it to the current ds
- * (0x00400000) and dereferences it, copying the data into a buffer which
- * it then runs directly through the MD5 hasher.  The 16 byte output of
- * the hash is then sent back to the server.
- *
- * If the client does not send any data back, or the data does not match
- * the data that the specific client should have, the client will get the
- * following message from "AOL Instant Messenger":
- *    "You have been disconnected from the AOL Instant Message Service (SM)
- *     for accessing the AOL network using unauthorized software.  You can
- *     download a FREE, fully featured, and authorized client, here
- *     http://www.aol.com/aim/download2.html"
- * The connection is then closed, receiving disconnect code 1, URL
- * http://www.aim.aol.com/errors/USER_LOGGED_OFF_NEW_LOGIN.html.
- *
- * Note, however, that numerous inconsistencies can cause the above error,
- * not just sending back a bad hash.  Do not immediately suspect this code
- * if you get disconnected.  AOL and the open/free software community have
- * played this game for a couple years now, generating the above message
- * on numerous occasions.
- *
- * Anyway, neener.  We win again.
- *
- */
-/* Client verification (group 1, subtype 0x1f) */
-static int memrequest(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	aim_rxcallback_t userfunc;
-	guint32 offset, len;
-	aim_tlvlist_t *list;
-	char *modname;
-
-	offset = aimbs_get32(bs);
-	len = aimbs_get32(bs);
-	list = aim_readtlvchain(bs);
-
-	modname = aim_gettlv_str(list, 0x0001, 1);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		return userfunc(sess, rx, offset, len, modname);
-	}
-
-	g_free(modname);
-	aim_freetlvchain(&list);
-
-	return 0;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0003) {
-		return hostonline(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == 0x0005) {
-		return redirect(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == 0x0007) {
-		return rateresp(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == 0x000a) {
-		return ratechange(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == 0x000b) {
-		return serverpause(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == 0x000d) {
-		return serverresume(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == 0x000f) {
-		return selfinfo(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == 0x0010) {
-		return evilnotify(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == 0x0012) {
-		return migrate(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == 0x0013) {
-		return motd(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == 0x0018) {
-		return hostversions(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == 0x001f) {
-		return memrequest(sess, mod, rx, snac, bs);
-	}
-
-	return 0;
-}
-
-int general_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x0001;
-	mod->version = 0x0003;
-	mod->toolid = 0x0110;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "general", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
-
Index: protocols/oscar/snac.c
===================================================================
--- protocols/oscar/snac.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,156 +1,0 @@
-/*
- *
- * Various SNAC-related dodads...
- *
- * outstanding_snacs is a list of aim_snac_t structs.  A SNAC should be added
- * whenever a new SNAC is sent and it should remain in the list until the
- * response for it has been receieved.
- *
- * cleansnacs() should be called periodically by the client in order
- * to facilitate the aging out of unreplied-to SNACs. This can and does
- * happen, so it should be handled.
- *
- */
-
-#include <aim.h>
-
-static aim_snacid_t aim_newsnac(aim_session_t *sess, aim_snac_t *newsnac);
-
-/*
- * Called from aim_session_init() to initialize the hash.
- */
-void aim_initsnachash(aim_session_t *sess)
-{
-	int i;
-
-	for (i = 0; i < AIM_SNAC_HASH_SIZE; i++) {
-		sess->snac_hash[i] = NULL;
-	}
-
-	return;
-}
-
-aim_snacid_t aim_cachesnac(aim_session_t *sess, const guint16 family, const guint16 type, const guint16 flags,
-                           const void *data, const int datalen)
-{
-	aim_snac_t snac;
-
-	snac.id = sess->snacid_next++;
-	snac.family = family;
-	snac.type = type;
-	snac.flags = flags;
-
-	if (datalen) {
-		if (!(snac.data = g_malloc(datalen))) {
-			return 0; /* er... */
-		}
-		memcpy(snac.data, data, datalen);
-	} else {
-		snac.data = NULL;
-	}
-
-	return aim_newsnac(sess, &snac);
-}
-
-/*
- * Clones the passed snac structure and caches it in the
- * list/hash.
- */
-static aim_snacid_t aim_newsnac(aim_session_t *sess, aim_snac_t *newsnac)
-{
-	aim_snac_t *snac;
-	int index;
-
-	if (!newsnac) {
-		return 0;
-	}
-
-	if (!(snac = g_malloc(sizeof(aim_snac_t)))) {
-		return 0;
-	}
-	memcpy(snac, newsnac, sizeof(aim_snac_t));
-	snac->issuetime = time(NULL);
-
-	index = snac->id % AIM_SNAC_HASH_SIZE;
-
-	snac->next = (aim_snac_t *) sess->snac_hash[index];
-	sess->snac_hash[index] = (void *) snac;
-
-	return snac->id;
-}
-
-/*
- * Finds a snac structure with the passed SNAC ID,
- * removes it from the list/hash, and returns a pointer to it.
- *
- * The returned structure must be freed by the caller.
- *
- */
-aim_snac_t *aim_remsnac(aim_session_t *sess, aim_snacid_t id)
-{
-	aim_snac_t *cur, **prev;
-	int index;
-
-	index = id % AIM_SNAC_HASH_SIZE;
-
-	for (prev = (aim_snac_t **) &sess->snac_hash[index]; (cur = *prev); ) {
-		if (cur->id == id) {
-			*prev = cur->next;
-			return cur;
-		} else {
-			prev = &cur->next;
-		}
-	}
-
-	return cur;
-}
-
-/*
- * This is for cleaning up old SNACs that either don't get replies or
- * a reply was never received for.  Garabage collection. Plain and simple.
- *
- * maxage is the _minimum_ age in seconds to keep SNACs.
- *
- */
-void aim_cleansnacs(aim_session_t *sess, int maxage)
-{
-	int i;
-
-	for (i = 0; i < AIM_SNAC_HASH_SIZE; i++) {
-		aim_snac_t *cur, **prev;
-		time_t curtime;
-
-		if (!sess->snac_hash[i]) {
-			continue;
-		}
-
-		curtime = time(NULL); /* done here in case we waited for the lock */
-
-		for (prev = (aim_snac_t **) &sess->snac_hash[i]; (cur = *prev); ) {
-			if ((curtime - cur->issuetime) > maxage) {
-
-				*prev = cur->next;
-
-				/* XXX should we have destructors here? */
-				g_free(cur->data);
-				g_free(cur);
-
-			} else {
-				prev = &cur->next;
-			}
-		}
-	}
-
-	return;
-}
-
-int aim_putsnac(aim_bstream_t *bs, guint16 family, guint16 subtype, guint16 flags, aim_snacid_t snacid)
-{
-
-	aimbs_put16(bs, family);
-	aimbs_put16(bs, subtype);
-	aimbs_put16(bs, flags);
-	aimbs_put32(bs, snacid);
-
-	return 10;
-}
Index: protocols/oscar/ssi.c
===================================================================
--- protocols/oscar/ssi.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,1339 +1,0 @@
-/*
- * Server-Side/Stored Information.
- *
- * Relatively new facility that allows storing of certain types of information,
- * such as a users buddy list, permit/deny list, and permit/deny preferences,
- * to be stored on the server, so that they can be accessed from any client.
- *
- * We keep a copy of the ssi data in sess->ssi, because the data needs to be
- * accessed for various reasons.  So all the "aim_ssi_itemlist_bleh" functions
- * near the top just manage the local data.
- *
- * The SNAC sending and receiving functions are lower down in the file, and
- * they're simpler.  They are in the order of the subtypes they deal with,
- * starting with the request rights function (subtype 0x0002), then parse
- * rights (subtype 0x0003), then--well, you get the idea.
- *
- * This is entirely too complicated.
- * You don't know the half of it.
- *
- * XXX - Test for memory leaks
- * XXX - Better parsing of rights, and use the rights info to limit adds
- *
- */
-
-#include <aim.h>
-#include "ssi.h"
-
-/**
- * Locally add a new item to the given item list.
- *
- * @param list A pointer to a pointer to the current list of items.
- * @param parent A pointer to the parent group, or NULL if the item should have no
- *        parent group (ie. the group ID# should be 0).
- * @param name A null terminated string of the name of the new item, or NULL if the
- *        item should have no name.
- * @param type The type of the item, 0x0001 for a contact, 0x0002 for a group, etc.
- * @return The newly created item.
- */
-static struct aim_ssi_item *aim_ssi_itemlist_add(struct aim_ssi_item **list, struct aim_ssi_item *parent, char *name,
-                                                 guint16 type)
-{
-	int i;
-	struct aim_ssi_item *cur, *newitem;
-
-	if (!(newitem = g_new0(struct aim_ssi_item, 1))) {
-		return NULL;
-	}
-
-	/* Set the name */
-	if (name) {
-		if (!(newitem->name = (char *) g_malloc((strlen(name) + 1) * sizeof(char)))) {
-			g_free(newitem);
-			return NULL;
-		}
-		strcpy(newitem->name, name);
-	} else {
-		newitem->name = NULL;
-	}
-
-	/* Set the group ID# and the buddy ID# */
-	newitem->gid = 0x0000;
-	newitem->bid = 0x0000;
-	if (type == AIM_SSI_TYPE_GROUP) {
-		if (name) {
-			do {
-				newitem->gid += 0x0001;
-				for (cur = *list, i = 0; ((cur) && (!i)); cur = cur->next) {
-					if ((cur->bid == newitem->bid) && (cur->gid == newitem->gid)) {
-						i = 1;
-					}
-				}
-			} while (i);
-		}
-	} else {
-		if (parent) {
-			newitem->gid = parent->gid;
-		}
-		do {
-			newitem->bid += 0x0001;
-			for (cur = *list, i = 0; ((cur) && (!i)); cur = cur->next) {
-				if ((cur->bid == newitem->bid) && (cur->gid == newitem->gid)) {
-					i = 1;
-				}
-			}
-		} while (i);
-	}
-
-	/* Set the rest */
-	newitem->type = type;
-	newitem->data = NULL;
-	newitem->next = *list;
-	*list = newitem;
-
-	return newitem;
-}
-
-/**
- * Locally rebuild the 0x00c8 TLV in the additional data of the given group.
- *
- * @param list A pointer to a pointer to the current list of items.
- * @param parentgroup A pointer to the group who's additional data you want to rebuild.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-static int aim_ssi_itemlist_rebuildgroup(struct aim_ssi_item **list, struct aim_ssi_item *parentgroup)
-{
-	int newlen; //, i;
-	struct aim_ssi_item *cur;
-
-	/* Free the old additional data */
-	if (parentgroup->data) {
-		aim_freetlvchain((aim_tlvlist_t **) &parentgroup->data);
-		parentgroup->data = NULL;
-	}
-
-	/* Find the length for the new additional data */
-	newlen = 0;
-	if (parentgroup->gid == 0x0000) {
-		for (cur = *list; cur; cur = cur->next) {
-			if ((cur->gid != 0x0000) && (cur->type == AIM_SSI_TYPE_GROUP)) {
-				newlen += 2;
-			}
-		}
-	} else {
-		for (cur = *list; cur; cur = cur->next) {
-			if ((cur->gid == parentgroup->gid) && (cur->type == AIM_SSI_TYPE_BUDDY)) {
-				newlen += 2;
-			}
-		}
-	}
-
-	/* Rebuild the additional data */
-	if (newlen > 0) {
-		guint8 *newdata;
-
-		if (!(newdata = (guint8 *) g_malloc((newlen) * sizeof(guint8)))) {
-			return -ENOMEM;
-		}
-		newlen = 0;
-		if (parentgroup->gid == 0x0000) {
-			for (cur = *list; cur; cur = cur->next) {
-				if ((cur->gid != 0x0000) && (cur->type == AIM_SSI_TYPE_GROUP)) {
-					newlen += aimutil_put16(newdata + newlen, cur->gid);
-				}
-			}
-		} else {
-			for (cur = *list; cur; cur = cur->next) {
-				if ((cur->gid == parentgroup->gid) && (cur->type == AIM_SSI_TYPE_BUDDY)) {
-					newlen += aimutil_put16(newdata + newlen, cur->bid);
-				}
-			}
-		}
-		aim_addtlvtochain_raw((aim_tlvlist_t **) &(parentgroup->data), 0x00c8, newlen, newdata);
-
-		g_free(newdata);
-	}
-
-	return 0;
-}
-
-/**
- * Locally free all of the stored buddy list information.
- *
- * @param sess The oscar session.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-static int aim_ssi_freelist(aim_session_t *sess)
-{
-	struct aim_ssi_item *cur, *delitem;
-
-	cur = sess->ssi.items;
-	while (cur) {
-		if (cur->name) {
-			g_free(cur->name);
-		}
-		if (cur->data) {
-			aim_freetlvchain((aim_tlvlist_t **) &cur->data);
-		}
-		delitem = cur;
-		cur = cur->next;
-		g_free(delitem);
-	}
-
-	sess->ssi.items = NULL;
-	sess->ssi.revision = 0;
-	sess->ssi.timestamp = (time_t) 0;
-
-	return 0;
-}
-
-/**
- * Locally find an item given a group ID# and a buddy ID#.
- *
- * @param list A pointer to the current list of items.
- * @param gid The group ID# of the desired item.
- * @param bid The buddy ID# of the desired item.
- * @return Return a pointer to the item if found, else return NULL;
- */
-struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, guint16 gid, guint16 bid)
-{
-	struct aim_ssi_item *cur;
-
-	for (cur = list; cur; cur = cur->next) {
-		if ((cur->gid == gid) && (cur->bid == bid)) {
-			return cur;
-		}
-	}
-	return NULL;
-}
-
-/**
- * Locally find an item given a group name, screen name, and type.  If group name
- * and screen name are null, then just return the first item of the given type.
- *
- * @param list A pointer to the current list of items.
- * @param gn The group name of the desired item.
- * @param bn The buddy name of the desired item.
- * @param type The type of the desired item.
- * @return Return a pointer to the item if found, else return NULL;
- */
-struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, char *gn, char *sn, guint16 type)
-{
-	struct aim_ssi_item *cur;
-
-	if (!list) {
-		return NULL;
-	}
-
-	if (gn && sn) { /* For finding buddies in groups */
-		for (cur = list; cur; cur = cur->next) {
-			if ((cur->type == type) && (cur->name) && !(aim_sncmp(cur->name, sn))) {
-				struct aim_ssi_item *curg;
-				for (curg = list; curg; curg = curg->next) {
-					if ((curg->type == AIM_SSI_TYPE_GROUP) && (curg->gid == cur->gid) &&
-					    (curg->name) && !(aim_sncmp(curg->name, gn))) {
-						return cur;
-					}
-				}
-			}
-		}
-
-	} else if (sn) { /* For finding groups, permits, denies, and ignores */
-		for (cur = list; cur; cur = cur->next) {
-			if ((cur->type == type) && (cur->name) && !(aim_sncmp(cur->name, sn))) {
-				return cur;
-			}
-		}
-
-		/* For stuff without names--permit deny setting, visibility mask, etc. */
-	} else { for (cur = list; cur; cur = cur->next) {
-			 if (cur->type == type) {
-				 return cur;
-			 }
-		 }
-	}
-
-	return NULL;
-}
-
-/**
- * Locally find the parent item of the given buddy name.
- *
- * @param list A pointer to the current list of items.
- * @param bn The buddy name of the desired item.
- * @return Return a pointer to the item if found, else return NULL;
- */
-struct aim_ssi_item *aim_ssi_itemlist_findparent(struct aim_ssi_item *list, char *sn)
-{
-	struct aim_ssi_item *cur, *curg;
-
-	if (!list || !sn) {
-		return NULL;
-	}
-	if (!(cur = aim_ssi_itemlist_finditem(list, NULL, sn, AIM_SSI_TYPE_BUDDY))) {
-		return NULL;
-	}
-	for (curg = list; curg; curg = curg->next) {
-		if ((curg->type == AIM_SSI_TYPE_GROUP) && (curg->gid == cur->gid)) {
-			return curg;
-		}
-	}
-	return NULL;
-}
-
-/**
- * Locally find the permit/deny setting item, and return the setting.
- *
- * @param list A pointer to the current list of items.
- * @return Return the current SSI permit deny setting, or 0 if no setting was found.
- */
-int aim_ssi_getpermdeny(struct aim_ssi_item *list)
-{
-	struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PDINFO);
-
-	if (cur) {
-		aim_tlvlist_t *tlvlist = cur->data;
-		if (tlvlist) {
-			aim_tlv_t *tlv = aim_gettlv(tlvlist, 0x00ca, 1);
-			if (tlv && tlv->value) {
-				return aimutil_get8(tlv->value);
-			}
-		}
-	}
-	return 0;
-}
-
-/**
- * Add the given packet to the holding queue.  We totally need to send SSI SNACs one at
- * a time, so we have a local queue where packets get put before they are sent, and
- * then we send stuff one at a time, nice and orderly-like.
- *
- * @param sess The oscar session.
- * @param conn The bos connection for this session.
- * @param fr The newly created SNAC that you want to send.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-static int aim_ssi_enqueue(aim_session_t *sess, aim_conn_t *conn, aim_frame_t *fr)
-{
-	aim_frame_t *cur;
-
-	if (!sess || !conn || !fr) {
-		return -EINVAL;
-	}
-
-	fr->next = NULL;
-	if (sess->ssi.holding_queue == NULL) {
-		sess->ssi.holding_queue = fr;
-		if (!sess->ssi.waiting_for_ack) {
-			aim_ssi_modbegin(sess, conn);
-		}
-	} else {
-		for (cur = sess->ssi.holding_queue; cur->next; cur = cur->next) {
-			;
-		}
-		cur->next = fr;
-	}
-
-	return 0;
-}
-
-/**
- * Send the next SNAC from the holding queue.  This is called
- * automatically when an ack from an add, mod, or del is received.
- * If the queue is empty, it sends the modend SNAC.
- *
- * @param sess The oscar session.
- * @param conn The bos connection for this session.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-static int aim_ssi_dispatch(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_frame_t *cur;
-
-	if (!sess || !conn) {
-		return -EINVAL;
-	}
-
-	if (!sess->ssi.waiting_for_ack) {
-		if (sess->ssi.holding_queue) {
-			sess->ssi.waiting_for_ack = 1;
-			cur = sess->ssi.holding_queue->next;
-			sess->ssi.holding_queue->next = NULL;
-			aim_tx_enqueue(sess, sess->ssi.holding_queue);
-			sess->ssi.holding_queue = cur;
-		} else {
-			aim_ssi_modend(sess, conn);
-		}
-	}
-
-	return 0;
-}
-
-/**
- * Add an array of screen names to the given group.
- *
- * @param sess The oscar session.
- * @param conn The bos connection for this session.
- * @param gn The name of the group to which you want to add these names.
- * @param sn An array of null terminated strings of the names you want to add.
- * @param num The number of screen names you are adding (size of the sn array).
- * @param flags 1 - Add with TLV(0x66)
- * @return Return 0 if no errors, otherwise return the error number.
- */
-int aim_ssi_addbuddies(aim_session_t *sess, aim_conn_t *conn, char *gn, char **sn, unsigned int num, unsigned int flags)
-{
-	struct aim_ssi_item *parentgroup, **newitems;
-	guint16 i;
-
-	if (!sess || !conn || !gn || !sn || !num) {
-		return -EINVAL;
-	}
-
-	/* Look up the parent group */
-	if (!(parentgroup = aim_ssi_itemlist_finditem(sess->ssi.items, NULL, gn, AIM_SSI_TYPE_GROUP))) {
-		aim_ssi_addgroups(sess, conn, &gn, 1);
-		if (!(parentgroup = aim_ssi_itemlist_finditem(sess->ssi.items, NULL, gn, AIM_SSI_TYPE_GROUP))) {
-			return -ENOMEM;
-		}
-	}
-
-	/* Allocate an array of pointers to each of the new items */
-	if (!(newitems = g_new0(struct aim_ssi_item *, num))) {
-		return -ENOMEM;
-	}
-
-	/* Add items to the local list, and index them in the array */
-	for (i = 0; i < num; i++) {
-		if (!(newitems[i] = aim_ssi_itemlist_add(&sess->ssi.items, parentgroup, sn[i], AIM_SSI_TYPE_BUDDY))) {
-			g_free(newitems);
-			return -ENOMEM;
-		} else if (flags & 1) {
-			aim_tlvlist_t *tl = NULL;
-			aim_addtlvtochain_noval(&tl, 0x66);
-			newitems[i]->data = tl;
-		}
-	}
-
-	/* Send the add item SNAC */
-	if ((i = aim_ssi_addmoddel(sess, conn, newitems, num, AIM_CB_SSI_ADD))) {
-		g_free(newitems);
-		return -i;
-	}
-
-	/* Free the array of pointers to each of the new items */
-	g_free(newitems);
-
-	/* Rebuild the additional data in the parent group */
-	if ((i = aim_ssi_itemlist_rebuildgroup(&sess->ssi.items, parentgroup))) {
-		return i;
-	}
-
-	/* Send the mod item SNAC */
-	if ((i = aim_ssi_addmoddel(sess, conn, &parentgroup, 1, AIM_CB_SSI_MOD))) {
-		return i;
-	}
-
-	/* Begin sending SSI SNACs */
-	if (!(i = aim_ssi_dispatch(sess, conn))) {
-		return i;
-	}
-
-	return 0;
-}
-
-/**
- * Add the master group (the group containing all groups).  This is called by
- * aim_ssi_addgroups, if necessary.
- *
- * @param sess The oscar session.
- * @param conn The bos connection for this session.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-int aim_ssi_addmastergroup(aim_session_t *sess, aim_conn_t *conn)
-{
-	struct aim_ssi_item *newitem;
-
-	if (!sess || !conn) {
-		return -EINVAL;
-	}
-
-	/* Add the item to the local list, and keep a pointer to it */
-	if (!(newitem = aim_ssi_itemlist_add(&sess->ssi.items, NULL, NULL, AIM_SSI_TYPE_GROUP))) {
-		return -ENOMEM;
-	}
-
-	/* If there are any existing groups (technically there shouldn't be, but */
-	/* just in case) then add their group ID#'s to the additional data */
-	aim_ssi_itemlist_rebuildgroup(&sess->ssi.items, newitem);
-
-	/* Send the add item SNAC */
-	aim_ssi_addmoddel(sess, conn, &newitem, 1, AIM_CB_SSI_ADD);
-
-	/* Begin sending SSI SNACs */
-	aim_ssi_dispatch(sess, conn);
-
-	return 0;
-}
-
-/**
- * Add an array of groups to the list.
- *
- * @param sess The oscar session.
- * @param conn The bos connection for this session.
- * @param gn An array of null terminated strings of the names you want to add.
- * @param num The number of groups names you are adding (size of the sn array).
- * @return Return 0 if no errors, otherwise return the error number.
- */
-int aim_ssi_addgroups(aim_session_t *sess, aim_conn_t *conn, char **gn, unsigned int num)
-{
-	struct aim_ssi_item *parentgroup, **newitems;
-	guint16 i;
-
-	if (!sess || !conn || !gn || !num) {
-		return -EINVAL;
-	}
-
-	/* Look up the parent group */
-	if (!(parentgroup = aim_ssi_itemlist_find(sess->ssi.items, 0, 0))) {
-		aim_ssi_addmastergroup(sess, conn);
-		if (!(parentgroup = aim_ssi_itemlist_find(sess->ssi.items, 0, 0))) {
-			return -ENOMEM;
-		}
-	}
-
-	/* Allocate an array of pointers to each of the new items */
-	if (!(newitems = g_new0(struct aim_ssi_item *, num))) {
-		return -ENOMEM;
-	}
-
-	/* Add items to the local list, and index them in the array */
-	for (i = 0; i < num; i++) {
-		if (!(newitems[i] = aim_ssi_itemlist_add(&sess->ssi.items, parentgroup, gn[i], AIM_SSI_TYPE_GROUP))) {
-			g_free(newitems);
-			return -ENOMEM;
-		}
-	}
-
-	/* Send the add item SNAC */
-	if ((i = aim_ssi_addmoddel(sess, conn, newitems, num, AIM_CB_SSI_ADD))) {
-		g_free(newitems);
-		return -i;
-	}
-
-	/* Free the array of pointers to each of the new items */
-	g_free(newitems);
-
-	/* Rebuild the additional data in the parent group */
-	if ((i = aim_ssi_itemlist_rebuildgroup(&sess->ssi.items, parentgroup))) {
-		return i;
-	}
-
-	/* Send the mod item SNAC */
-	if ((i = aim_ssi_addmoddel(sess, conn, &parentgroup, 1, AIM_CB_SSI_MOD))) {
-		return i;
-	}
-
-	/* Begin sending SSI SNACs */
-	if (!(i = aim_ssi_dispatch(sess, conn))) {
-		return i;
-	}
-
-	return 0;
-}
-
-/**
- * Add an array of a certain type of item to the list.  This can be used for
- * permit buddies, deny buddies, ICQ's ignore buddies, and probably other
- * types, also.
- *
- * @param sess The oscar session.
- * @param conn The bos connection for this session.
- * @param sn An array of null terminated strings of the names you want to add.
- * @param num The number of groups names you are adding (size of the sn array).
- * @param type The type of item you want to add.  See the AIM_SSI_TYPE_BLEH
- *        #defines in aim.h.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-int aim_ssi_addpord(aim_session_t *sess, aim_conn_t *conn, char **sn, unsigned int num, guint16 type)
-{
-	struct aim_ssi_item **newitems;
-	guint16 i;
-
-	if (!sess || !conn || !sn || !num) {
-		return -EINVAL;
-	}
-
-	/* Allocate an array of pointers to each of the new items */
-	if (!(newitems = g_new0(struct aim_ssi_item *, num))) {
-		return -ENOMEM;
-	}
-
-	/* Add items to the local list, and index them in the array */
-	for (i = 0; i < num; i++) {
-		if (!(newitems[i] = aim_ssi_itemlist_add(&sess->ssi.items, NULL, sn[i], type))) {
-			g_free(newitems);
-			return -ENOMEM;
-		}
-	}
-
-	/* Send the add item SNAC */
-	if ((i = aim_ssi_addmoddel(sess, conn, newitems, num, AIM_CB_SSI_ADD))) {
-		g_free(newitems);
-		return -i;
-	}
-
-	/* Free the array of pointers to each of the new items */
-	g_free(newitems);
-
-	/* Begin sending SSI SNACs */
-	if (!(i = aim_ssi_dispatch(sess, conn))) {
-		return i;
-	}
-
-	return 0;
-}
-
-/**
- * Move a buddy from one group to another group.  This basically just deletes the
- * buddy and re-adds it.
- *
- * @param sess The oscar session.
- * @param conn The bos connection for this session.
- * @param oldgn The group that the buddy is currently in.
- * @param newgn The group that the buddy should be moved in to.
- * @param sn The name of the buddy to be moved.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-int aim_ssi_movebuddy(aim_session_t *sess, aim_conn_t *conn, char *oldgn, char *newgn, char *sn)
-{
-	struct aim_ssi_item **groups, *buddy, *cur;
-	guint16 i;
-
-	if (!sess || !conn || !oldgn || !newgn || !sn) {
-		return -EINVAL;
-	}
-
-	/* Look up the buddy */
-	if (!(buddy = aim_ssi_itemlist_finditem(sess->ssi.items, NULL, sn, AIM_SSI_TYPE_BUDDY))) {
-		return -ENOMEM;
-	}
-
-	/* Allocate an array of pointers to the two groups */
-	if (!(groups = g_new0(struct aim_ssi_item *, 2))) {
-		return -ENOMEM;
-	}
-
-	/* Look up the old parent group */
-	if (!(groups[0] = aim_ssi_itemlist_finditem(sess->ssi.items, NULL, oldgn, AIM_SSI_TYPE_GROUP))) {
-		g_free(groups);
-		return -ENOMEM;
-	}
-
-	/* Look up the new parent group */
-	if (!(groups[1] = aim_ssi_itemlist_finditem(sess->ssi.items, NULL, newgn, AIM_SSI_TYPE_GROUP))) {
-		g_free(groups);
-		return -ENOMEM;
-	}
-
-	/* Send the delete item SNAC */
-	aim_ssi_addmoddel(sess, conn, &buddy, 1, AIM_CB_SSI_DEL);
-
-	/* Put the buddy in the new group */
-	buddy->gid = groups[1]->gid;
-
-	/* Assign a new buddy ID#, because the new group might already have a buddy with this ID# */
-	buddy->bid = 0;
-	do {
-		buddy->bid += 0x0001;
-		for (cur = sess->ssi.items, i = 0; ((cur) && (!i)); cur = cur->next) {
-			if ((cur->bid == buddy->bid) && (cur->gid == buddy->gid) && (cur->type == AIM_SSI_TYPE_BUDDY) &&
-			    (cur->name) && aim_sncmp(cur->name, buddy->name)) {
-				i = 1;
-			}
-		}
-	} while (i);
-
-	/* Rebuild the additional data in the two parent groups */
-	aim_ssi_itemlist_rebuildgroup(&sess->ssi.items, groups[0]);
-	aim_ssi_itemlist_rebuildgroup(&sess->ssi.items, groups[1]);
-
-	/* Send the add item SNAC */
-	aim_ssi_addmoddel(sess, conn, &buddy, 1, AIM_CB_SSI_ADD);
-
-	/* Send the mod item SNAC */
-	aim_ssi_addmoddel(sess, conn, groups, 2, AIM_CB_SSI_MOD);
-
-	/* Free the temporary array */
-	g_free(groups);
-
-	/* Begin sending SSI SNACs */
-	aim_ssi_dispatch(sess, conn);
-
-	return 0;
-}
-
-/**
- * Delete an array of screen names from the given group.
- *
- * @param sess The oscar session.
- * @param conn The bos connection for this session.
- * @param gn The name of the group from which you want to delete these names.
- * @param sn An array of null terminated strings of the names you want to delete.
- * @param num The number of screen names you are deleting (size of the sn array).
- * @return Return 0 if no errors, otherwise return the error number.
- */
-int aim_ssi_delbuddies(aim_session_t *sess, aim_conn_t *conn, char *gn, char **sn, unsigned int num)
-{
-	struct aim_ssi_item *cur, *parentgroup, **delitems;
-	int i;
-
-	if (!sess || !conn || !gn || !sn || !num) {
-		return -EINVAL;
-	}
-
-	/* Look up the parent group */
-	if (!(parentgroup = aim_ssi_itemlist_finditem(sess->ssi.items, NULL, gn, AIM_SSI_TYPE_GROUP))) {
-		return -EINVAL;
-	}
-
-	/* Allocate an array of pointers to each of the items to be deleted */
-	delitems = g_new0(struct aim_ssi_item *, num);
-
-	/* Make the delitems array a pointer to the aim_ssi_item structs to be deleted */
-	for (i = 0; i < num; i++) {
-		if (!(delitems[i] = aim_ssi_itemlist_finditem(sess->ssi.items, NULL, sn[i], AIM_SSI_TYPE_BUDDY))) {
-			g_free(delitems);
-			return -EINVAL;
-		}
-
-		/* Remove the delitems from the item list */
-		if (sess->ssi.items == delitems[i]) {
-			sess->ssi.items = sess->ssi.items->next;
-		} else {
-			for (cur = sess->ssi.items; (cur->next && (cur->next != delitems[i])); cur = cur->next) {
-				;
-			}
-			if (cur->next) {
-				cur->next = cur->next->next;
-			}
-		}
-	}
-
-	/* Send the del item SNAC */
-	aim_ssi_addmoddel(sess, conn, delitems, num, AIM_CB_SSI_DEL);
-
-	/* Free the items */
-	for (i = 0; i < num; i++) {
-		if (delitems[i]->name) {
-			g_free(delitems[i]->name);
-		}
-		if (delitems[i]->data) {
-			aim_freetlvchain((aim_tlvlist_t **) &delitems[i]->data);
-		}
-		g_free(delitems[i]);
-	}
-	g_free(delitems);
-
-	/* Rebuild the additional data in the parent group */
-	aim_ssi_itemlist_rebuildgroup(&sess->ssi.items, parentgroup);
-
-	/* Send the mod item SNAC */
-	aim_ssi_addmoddel(sess, conn, &parentgroup, 1, AIM_CB_SSI_MOD);
-
-	/* Delete the group, but only if it's empty */
-	if (!parentgroup->data) {
-		aim_ssi_delgroups(sess, conn, &parentgroup->name, 1);
-	}
-
-	/* Begin sending SSI SNACs */
-	aim_ssi_dispatch(sess, conn);
-
-	return 0;
-}
-
-/**
- * Delete the master group from the item list.  There can be only one.
- * Er, so just find the one master group and delete it.
- *
- * @param sess The oscar session.
- * @param conn The bos connection for this session.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-int aim_ssi_delmastergroup(aim_session_t *sess, aim_conn_t *conn)
-{
-	struct aim_ssi_item *cur, *delitem;
-
-	if (!sess || !conn) {
-		return -EINVAL;
-	}
-
-	/* Make delitem a pointer to the aim_ssi_item to be deleted */
-	if (!(delitem = aim_ssi_itemlist_find(sess->ssi.items, 0, 0))) {
-		return -EINVAL;
-	}
-
-	/* Remove delitem from the item list */
-	if (sess->ssi.items == delitem) {
-		sess->ssi.items = sess->ssi.items->next;
-	} else {
-		for (cur = sess->ssi.items; (cur->next && (cur->next != delitem)); cur = cur->next) {
-			;
-		}
-		if (cur->next) {
-			cur->next = cur->next->next;
-		}
-	}
-
-	/* Send the del item SNAC */
-	aim_ssi_addmoddel(sess, conn, &delitem, 1, AIM_CB_SSI_DEL);
-
-	/* Free the item */
-	if (delitem->name) {
-		g_free(delitem->name);
-	}
-	if (delitem->data) {
-		aim_freetlvchain((aim_tlvlist_t **) &delitem->data);
-	}
-	g_free(delitem);
-
-	/* Begin sending SSI SNACs */
-	aim_ssi_dispatch(sess, conn);
-
-	return 0;
-}
-
-/**
- * Delete an array of groups.
- *
- * @param sess The oscar session.
- * @param conn The bos connection for this session.
- * @param gn An array of null terminated strings of the groups you want to delete.
- * @param num The number of groups you are deleting (size of the gn array).
- * @return Return 0 if no errors, otherwise return the error number.
- */
-int aim_ssi_delgroups(aim_session_t *sess, aim_conn_t *conn, char **gn, unsigned int num)
-{
-	struct aim_ssi_item *cur, *parentgroup, **delitems;
-	int i;
-
-	if (!sess || !conn || !gn || !num) {
-		return -EINVAL;
-	}
-
-	/* Look up the parent group */
-	if (!(parentgroup = aim_ssi_itemlist_find(sess->ssi.items, 0, 0))) {
-		return -EINVAL;
-	}
-
-	/* Allocate an array of pointers to each of the items to be deleted */
-	delitems = g_new0(struct aim_ssi_item *, num);
-
-	/* Make the delitems array a pointer to the aim_ssi_item structs to be deleted */
-	for (i = 0; i < num; i++) {
-		if (!(delitems[i] = aim_ssi_itemlist_finditem(sess->ssi.items, NULL, gn[i], AIM_SSI_TYPE_GROUP))) {
-			g_free(delitems);
-			return -EINVAL;
-		}
-
-		/* Remove the delitems from the item list */
-		if (sess->ssi.items == delitems[i]) {
-			sess->ssi.items = sess->ssi.items->next;
-		} else {
-			for (cur = sess->ssi.items; (cur->next && (cur->next != delitems[i])); cur = cur->next) {
-				;
-			}
-			if (cur->next) {
-				cur->next = cur->next->next;
-			}
-		}
-	}
-
-	/* Send the del item SNAC */
-	aim_ssi_addmoddel(sess, conn, delitems, num, AIM_CB_SSI_DEL);
-
-	/* Free the items */
-	for (i = 0; i < num; i++) {
-		if (delitems[i]->name) {
-			g_free(delitems[i]->name);
-		}
-		if (delitems[i]->data) {
-			aim_freetlvchain((aim_tlvlist_t **) &delitems[i]->data);
-		}
-		g_free(delitems[i]);
-	}
-	g_free(delitems);
-
-	/* Rebuild the additional data in the parent group */
-	aim_ssi_itemlist_rebuildgroup(&sess->ssi.items, parentgroup);
-
-	/* Send the mod item SNAC */
-	aim_ssi_addmoddel(sess, conn, &parentgroup, 1, AIM_CB_SSI_MOD);
-
-	/* Delete the group, but only if it's empty */
-	if (!parentgroup->data) {
-		aim_ssi_delmastergroup(sess, conn);
-	}
-
-	/* Begin sending SSI SNACs */
-	aim_ssi_dispatch(sess, conn);
-
-	return 0;
-}
-
-/**
- * Delete an array of a certain type of item from the list.  This can be
- * used for permit buddies, deny buddies, ICQ's ignore buddies, and
- * probably other types, also.
- *
- * @param sess The oscar session.
- * @param conn The bos connection for this session.
- * @param sn An array of null terminated strings of the items you want to delete.
- * @param num The number of items you are deleting (size of the sn array).
- * @return Return 0 if no errors, otherwise return the error number.
- */
-int aim_ssi_delpord(aim_session_t *sess, aim_conn_t *conn, char **sn, unsigned int num, guint16 type)
-{
-	struct aim_ssi_item *cur, **delitems;
-	int i;
-
-	if (!sess || !conn || !sn || !num || (type != AIM_SSI_TYPE_PERMIT && type != AIM_SSI_TYPE_DENY)) {
-		return -EINVAL;
-	}
-
-	/* Allocate an array of pointers to each of the items to be deleted */
-	delitems = g_new0(struct aim_ssi_item *, num);
-
-	/* Make the delitems array a pointer to the aim_ssi_item structs to be deleted */
-	for (i = 0; i < num; i++) {
-		if (!(delitems[i] = aim_ssi_itemlist_finditem(sess->ssi.items, NULL, sn[i], type))) {
-			g_free(delitems);
-			return -EINVAL;
-		}
-
-		/* Remove the delitems from the item list */
-		if (sess->ssi.items == delitems[i]) {
-			sess->ssi.items = sess->ssi.items->next;
-		} else {
-			for (cur = sess->ssi.items; (cur->next && (cur->next != delitems[i])); cur = cur->next) {
-				;
-			}
-			if (cur->next) {
-				cur->next = cur->next->next;
-			}
-		}
-	}
-
-	/* Send the del item SNAC */
-	aim_ssi_addmoddel(sess, conn, delitems, num, AIM_CB_SSI_DEL);
-
-	/* Free the items */
-	for (i = 0; i < num; i++) {
-		if (delitems[i]->name) {
-			g_free(delitems[i]->name);
-		}
-		if (delitems[i]->data) {
-			aim_freetlvchain((aim_tlvlist_t **) &delitems[i]->data);
-		}
-		g_free(delitems[i]);
-	}
-	g_free(delitems);
-
-	/* Begin sending SSI SNACs */
-	aim_ssi_dispatch(sess, conn);
-
-	return 0;
-}
-
-/*
- * Request SSI Rights.
- */
-int aim_ssi_reqrights(aim_session_t *sess, aim_conn_t *conn)
-{
-	return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_REQRIGHTS);
-}
-
-/*
- * SSI Rights Information.
- */
-static int parserights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx);
-	}
-
-	return ret;
-}
-
-int aim_ssi_reqalldata(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-
-	if (!sess || !conn) {
-		return -EINVAL;
-	}
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_REQFULLLIST, 0x0000, NULL, 0);
-
-	aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_REQFULLLIST, 0x0000, snacid);
-
-	aim_tx_enqueue(sess, fr);
-
-	return 0;
-}
-
-/*
- * SSI Data.
- */
-static int parsedata(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	struct aim_ssi_item *cur = NULL;
-	guint8 fmtver; /* guess */
-	guint16 revision;
-	guint32 timestamp;
-
-	/* When you set the version for the SSI family to 2-4, the beginning of this changes.
-	 * Instead of the version and then the revision, there is "0x0006" and then a type
-	 * 0x0001 TLV containing the 2 byte SSI family version that you sent earlier.  Also,
-	 * the SNAC flags go from 0x0000 to 0x8000.  I guess the 0x0006 is the length of the
-	 * TLV(s) that follow.  The rights SNAC does the same thing, with the differing flag
-	 * and everything.
-	 */
-
-	fmtver = aimbs_get8(bs); /* Version of ssi data.  Should be 0x00 */
-	revision = aimbs_get16(bs); /* # of times ssi data has been modified */
-	if (revision != 0) {
-		sess->ssi.revision = revision;
-	}
-
-	for (cur = sess->ssi.items; cur && cur->next; cur = cur->next) {
-		;
-	}
-
-	while (aim_bstream_empty(bs) > 4) { /* last four bytes are stamp */
-		guint16 namelen, tbslen;
-
-		if (!sess->ssi.items) {
-			if (!(sess->ssi.items = g_new0(struct aim_ssi_item, 1))) {
-				return -ENOMEM;
-			}
-			cur = sess->ssi.items;
-		} else {
-			if (!(cur->next = g_new0(struct aim_ssi_item, 1))) {
-				return -ENOMEM;
-			}
-			cur = cur->next;
-		}
-
-		if ((namelen = aimbs_get16(bs))) {
-			cur->name = aimbs_getstr(bs, namelen);
-		}
-		cur->gid = aimbs_get16(bs);
-		cur->bid = aimbs_get16(bs);
-		cur->type = aimbs_get16(bs);
-
-		if ((tbslen = aimbs_get16(bs))) {
-			aim_bstream_t tbs;
-
-			aim_bstream_init(&tbs, bs->data + bs->offset /* XXX */, tbslen);
-			cur->data = (void *) aim_readtlvchain(&tbs);
-			aim_bstream_advance(bs, tbslen);
-		}
-	}
-
-	timestamp = aimbs_get32(bs);
-	if (timestamp != 0) {
-		sess->ssi.timestamp = timestamp;
-	}
-	sess->ssi.received_data = 1;
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, fmtver, sess->ssi.revision, sess->ssi.timestamp, sess->ssi.items);
-	}
-
-	return ret;
-}
-
-/*
- * SSI Data Enable Presence.
- *
- * Should be sent after receiving 13/6 or 13/f to tell the server you
- * are ready to begin using the list.  It will promptly give you the
- * presence information for everyone in your list and put your permit/deny
- * settings into effect.
- *
- */
-int aim_ssi_enable(aim_session_t *sess, aim_conn_t *conn)
-{
-	return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, 0x0007);
-}
-
-/*
- * Stuff for SSI authorizations. The code used to work with the old im_ch4
- * messages, but those are supposed to be obsolete. This is probably
- * ICQ-specific.
- */
-
-/**
- * Request authorization to add someone to the server-side buddy list.
- *
- * @param sess The oscar session.
- * @param conn The bos connection for this session.
- * @param uin The contact's ICQ UIN.
- * @param reason The reason string to send with the request.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-int aim_ssi_auth_request(aim_session_t *sess, aim_conn_t *conn, char *uin, char *reason)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	int snaclen;
-
-	snaclen = 10 + 1 + strlen(uin) + 2 + strlen(reason) + 2;
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, snaclen))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREQ, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREQ, 0x0000, snacid);
-
-	aimbs_put8(&fr->data, strlen(uin));
-	aimbs_putraw(&fr->data, (guint8 *) uin, strlen(uin));
-	aimbs_put16(&fr->data, strlen(reason));
-	aimbs_putraw(&fr->data, (guint8 *) reason, strlen(reason));
-	aimbs_put16(&fr->data, 0);
-
-	aim_tx_enqueue(sess, fr);
-
-	return(0);
-}
-
-/**
- * Reply to an authorization request to add someone to the server-side buddy list.
- *
- * @param sess The oscar session.
- * @param conn The bos connection for this session.
- * @param uin The contact's ICQ UIN.
- * @param yesno 1 == Permit, 0 == Deny
- * @param reason The reason string to send with the request.
- * @return Return 0 if no errors, otherwise return the error number.
- */
-int aim_ssi_auth_reply(aim_session_t *sess, aim_conn_t *conn, char *uin, int yesno, char *reason)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	int snaclen;
-
-	snaclen = 10 + 1 + strlen(uin) + 3 + strlen(reason);
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, snaclen))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREP, 0x0000, NULL, 0);
-	aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREP, 0x0000, snacid);
-
-	aimbs_put8(&fr->data, strlen(uin));
-	aimbs_putraw(&fr->data, (guint8 *) uin, strlen(uin));
-	aimbs_put8(&fr->data, yesno);
-	aimbs_put16(&fr->data, strlen(reason));
-	aimbs_putraw(&fr->data, (guint8 *) reason, strlen(reason));
-
-	aim_tx_enqueue(sess, fr);
-
-	return(0);
-}
-
-
-/*
- * SSI Add/Mod/Del Item(s).
- *
- * Sends the SNAC to add, modify, or delete an item from the server-stored
- * information.  These 3 SNACs all have an identical structure.  The only
- * difference is the subtype that is set for the SNAC.
- *
- */
-int aim_ssi_addmoddel(aim_session_t *sess, aim_conn_t *conn, struct aim_ssi_item **items, unsigned int num,
-                      guint16 subtype)
-{
-	aim_frame_t *fr;
-	aim_snacid_t snacid;
-	int i, snaclen, listlen;
-	char *list = NULL;
-
-	if (!sess || !conn || !items || !num) {
-		return -EINVAL;
-	}
-
-	snaclen = 10; /* For family, subtype, flags, and SNAC ID */
-	listlen = 0;
-	for (i = 0; i < num; i++) {
-		snaclen += 10; /* For length, GID, BID, type, and length */
-		if (items[i]->name) {
-			snaclen += strlen(items[i]->name);
-
-			if (subtype == AIM_CB_SSI_ADD) {
-				list = g_realloc(list, listlen + strlen(items[i]->name) + 1);
-				strcpy(list + listlen, items[i]->name);
-				listlen += strlen(items[i]->name) + 1;
-			}
-		} else {
-			if (subtype == AIM_CB_SSI_ADD) {
-				list = g_realloc(list, listlen + 1);
-				list[listlen] = '\0';
-				listlen++;
-			}
-		}
-		if (items[i]->data) {
-			snaclen += aim_sizetlvchain((aim_tlvlist_t **) &items[i]->data);
-		}
-	}
-
-	if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, snaclen))) {
-		return -ENOMEM;
-	}
-
-	snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, subtype, 0x0000, list, list ? listlen : 0);
-	aim_putsnac(&fr->data, AIM_CB_FAM_SSI, subtype, 0x0000, snacid);
-
-	g_free(list);
-
-	for (i = 0; i < num; i++) {
-		aimbs_put16(&fr->data, items[i]->name ? strlen(items[i]->name) : 0);
-		if (items[i]->name) {
-			aimbs_putraw(&fr->data, (guint8 *) items[i]->name, strlen(items[i]->name));
-		}
-		aimbs_put16(&fr->data, items[i]->gid);
-		aimbs_put16(&fr->data, items[i]->bid);
-		aimbs_put16(&fr->data, items[i]->type);
-		aimbs_put16(&fr->data, items[i]->data ? aim_sizetlvchain((aim_tlvlist_t **) &items[i]->data) : 0);
-		if (items[i]->data) {
-			aim_writetlvchain(&fr->data, (aim_tlvlist_t **) &items[i]->data);
-		}
-	}
-
-	aim_ssi_enqueue(sess, conn, fr);
-
-	return 0;
-}
-
-/*
- * SSI Add/Mod/Del Ack.
- *
- * Response to add, modify, or delete SNAC (sent with aim_ssi_addmoddel).
- *
- */
-static int parseack(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-	aim_snac_t *origsnac;
-
-	sess->ssi.waiting_for_ack = 0;
-	aim_ssi_dispatch(sess, rx->conn);
-
-	origsnac = aim_remsnac(sess, snac->id);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx, origsnac);
-	}
-
-	if (origsnac) {
-		g_free(origsnac->data);
-		g_free(origsnac);
-	}
-
-	return ret;
-}
-
-/*
- * SSI Begin Data Modification.
- *
- * Tells the server you're going to start modifying data.
- *
- */
-int aim_ssi_modbegin(aim_session_t *sess, aim_conn_t *conn)
-{
-	return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_EDITSTART);
-}
-
-/*
- * SSI End Data Modification.
- *
- * Tells the server you're done modifying data.
- *
- */
-int aim_ssi_modend(aim_session_t *sess, aim_conn_t *conn)
-{
-	return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_EDITSTOP);
-}
-
-/*
- * SSI Data Unchanged.
- *
- * Response to aim_ssi_reqdata() if the server-side data is not newer than
- * posted local stamp/revision.
- *
- */
-static int parsedataunchanged(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac,
-                              aim_bstream_t *bs)
-{
-	int ret = 0;
-	aim_rxcallback_t userfunc;
-
-	sess->ssi.received_data = 1;
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		ret = userfunc(sess, rx);
-	}
-
-	return ret;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == AIM_CB_SSI_RIGHTSINFO) {
-		return parserights(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == AIM_CB_SSI_LIST) {
-		return parsedata(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == AIM_CB_SSI_SRVACK) {
-		return parseack(sess, mod, rx, snac, bs);
-	} else if (snac->subtype == AIM_CB_SSI_NOLIST) {
-		return parsedataunchanged(sess, mod, rx, snac, bs);
-	}
-
-	return 0;
-}
-
-static void ssi_shutdown(aim_session_t *sess, aim_module_t *mod)
-{
-	aim_ssi_freelist(sess);
-
-	return;
-}
-
-int ssi_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = AIM_CB_FAM_SSI;
-	mod->version = 0x0003;
-	mod->toolid = 0x0110;
-	mod->toolversion = 0x0629;
-	mod->flags = 0;
-	strncpy(mod->name, "ssi", sizeof(mod->name));
-	mod->snachandler = snachandler;
-	mod->shutdown = ssi_shutdown;
-
-	return 0;
-}
Index: protocols/oscar/ssi.h
===================================================================
--- protocols/oscar/ssi.h	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,74 +1,0 @@
-#ifndef __OSCAR_SSI_H__
-#define __OSCAR_SSI_H__
-
-#define AIM_CB_FAM_SSI 0x0013 /* Server stored information */
-
-/*
- * SNAC Family: Server-Stored Buddy Lists
- */
-#define AIM_CB_SSI_ERROR 0x0001
-#define AIM_CB_SSI_REQRIGHTS 0x0002
-#define AIM_CB_SSI_RIGHTSINFO 0x0003
-#define AIM_CB_SSI_REQFULLLIST 0x0004
-#define AIM_CB_SSI_REQLIST 0x0005
-#define AIM_CB_SSI_LIST 0x0006
-#define AIM_CB_SSI_ACTIVATE 0x0007
-#define AIM_CB_SSI_ADD 0x0008
-#define AIM_CB_SSI_MOD 0x0009
-#define AIM_CB_SSI_DEL 0x000A
-#define AIM_CB_SSI_SRVACK 0x000E
-#define AIM_CB_SSI_NOLIST 0x000F
-#define AIM_CB_SSI_EDITSTART 0x0011
-#define AIM_CB_SSI_EDITSTOP 0x0012
-#define AIM_CB_SSI_SENDAUTHREQ 0x0018
-#define AIM_CB_SSI_SERVAUTHREQ 0x0019
-#define AIM_CB_SSI_SENDAUTHREP 0x001A
-#define AIM_CB_SSI_SERVAUTHREP 0x001B
-
-
-#define AIM_SSI_TYPE_BUDDY         0x0000
-#define AIM_SSI_TYPE_GROUP         0x0001
-#define AIM_SSI_TYPE_PERMIT        0x0002
-#define AIM_SSI_TYPE_DENY          0x0003
-#define AIM_SSI_TYPE_PDINFO        0x0004
-#define AIM_SSI_TYPE_PRESENCEPREFS 0x0005
-
-struct aim_ssi_item {
-	char *name;
-	guint16 gid;
-	guint16 bid;
-	guint16 type;
-	void *data;
-	struct aim_ssi_item *next;
-};
-
-/* These build the actual SNACs and queue them to be sent */
-int aim_ssi_reqrights(aim_session_t *sess, aim_conn_t *conn);
-int aim_ssi_reqalldata(aim_session_t *sess, aim_conn_t *conn);
-int aim_ssi_enable(aim_session_t *sess, aim_conn_t *conn);
-int aim_ssi_addmoddel(aim_session_t *sess, aim_conn_t *conn, struct aim_ssi_item **items, unsigned int num,
-                      guint16 subtype);
-int aim_ssi_modbegin(aim_session_t *sess, aim_conn_t *conn);
-int aim_ssi_modend(aim_session_t *sess, aim_conn_t *conn);
-
-/* These handle the local variables */
-struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, guint16 gid, guint16 bid);
-struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, char *gn, char *sn, guint16 type);
-struct aim_ssi_item *aim_ssi_itemlist_findparent(struct aim_ssi_item *list, char *sn);
-int aim_ssi_getpermdeny(struct aim_ssi_item *list);
-
-/* Send packets */
-int aim_ssi_addbuddies(aim_session_t *sess, aim_conn_t *conn, char *gn, char **sn, unsigned int num,
-                       unsigned int flags);
-int aim_ssi_addmastergroup(aim_session_t *sess, aim_conn_t *conn);
-int aim_ssi_addgroups(aim_session_t *sess, aim_conn_t *conn, char **gn, unsigned int num);
-int aim_ssi_addpord(aim_session_t *sess, aim_conn_t *conn, char **sn, unsigned int num, guint16 type);
-int aim_ssi_movebuddy(aim_session_t *sess, aim_conn_t *conn, char *oldgn, char *newgn, char *sn);
-int aim_ssi_delbuddies(aim_session_t *sess, aim_conn_t *conn, char *gn, char **sn, unsigned int num);
-int aim_ssi_delmastergroup(aim_session_t *sess, aim_conn_t *conn);
-int aim_ssi_delgroups(aim_session_t *sess, aim_conn_t *conn, char **gn, unsigned int num);
-int aim_ssi_delpord(aim_session_t *sess, aim_conn_t *conn, char **sn, unsigned int num, guint16 type);
-int aim_ssi_auth_request(aim_session_t *sess, aim_conn_t *conn, char *uin, char *reason);
-int aim_ssi_auth_reply(aim_session_t *sess, aim_conn_t *conn, char *uin, int yesno, char *reason);
-
-#endif /* __OSCAR_SSI_H__ */
Index: protocols/oscar/stats.c
===================================================================
--- protocols/oscar/stats.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,41 +1,0 @@
-
-#include <aim.h>
-
-static int reportinterval(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac,
-                          aim_bstream_t *bs)
-{
-	guint16 interval;
-	aim_rxcallback_t userfunc;
-
-	interval = aimbs_get16(bs);
-
-	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
-		return userfunc(sess, rx, interval);
-	}
-
-	return 0;
-}
-
-static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
-{
-
-	if (snac->subtype == 0x0002) {
-		return reportinterval(sess, mod, rx, snac, bs);
-	}
-
-	return 0;
-}
-
-int stats_modfirst(aim_session_t *sess, aim_module_t *mod)
-{
-
-	mod->family = 0x000b;
-	mod->version = 0x0001;
-	mod->toolid = 0x0104;
-	mod->toolversion = 0x0001;
-	mod->flags = 0;
-	strncpy(mod->name, "stats", sizeof(mod->name));
-	mod->snachandler = snachandler;
-
-	return 0;
-}
Index: protocols/oscar/tlv.c
===================================================================
--- protocols/oscar/tlv.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,578 +1,0 @@
-#include <aim.h>
-
-static void freetlv(aim_tlv_t **oldtlv)
-{
-	if (!oldtlv || !*oldtlv) {
-		return;
-	}
-
-	g_free((*oldtlv)->value);
-	g_free(*oldtlv);
-	*oldtlv = NULL;
-}
-
-/**
- * aim_readtlvchain - Read a TLV chain from a buffer.
- * @buf: Input buffer
- * @maxlen: Length of input buffer
- *
- * Reads and parses a series of TLV patterns from a data buffer; the
- * returned structure is manipulatable with the rest of the TLV
- * routines.  When done with a TLV chain, aim_freetlvchain() should
- * be called to free the dynamic substructures.
- *
- * XXX There should be a flag setable here to have the tlvlist contain
- * bstream references, so that at least the ->value portion of each
- * element doesn't need to be malloc/memcpy'd.  This could prove to be
- * just as efficient as the in-place TLV parsing used in a couple places
- * in libfaim.
- *
- */
-aim_tlvlist_t *aim_readtlvchain(aim_bstream_t *bs)
-{
-	aim_tlvlist_t *list = NULL, *cur;
-	guint16 type, length;
-
-	while (aim_bstream_empty(bs)) {
-
-		type = aimbs_get16(bs);
-		length = aimbs_get16(bs);
-
-		cur = g_new0(aim_tlvlist_t, 1);
-
-		cur->tlv = g_new0(aim_tlv_t, 1);
-		cur->tlv->type = type;
-		if ((cur->tlv->length = length)) {
-			cur->tlv->value = aimbs_getraw(bs, length);
-		}
-
-		cur->next = list;
-		list = cur;
-	}
-
-	return list;
-}
-
-/**
- * aim_freetlvchain - Free a TLV chain structure
- * @list: Chain to be freed
- *
- * Walks the list of TLVs in the passed TLV chain and
- * frees each one. Note that any references to this data
- * should be removed before calling this.
- *
- */
-void aim_freetlvchain(aim_tlvlist_t **list)
-{
-	aim_tlvlist_t *cur;
-
-	if (!list || !*list) {
-		return;
-	}
-
-	for (cur = *list; cur; ) {
-		aim_tlvlist_t *tmp;
-
-		freetlv(&cur->tlv);
-
-		tmp = cur->next;
-		g_free(cur);
-		cur = tmp;
-	}
-
-	list = NULL;
-
-	return;
-}
-
-/**
- * aim_counttlvchain - Count the number of TLVs in a chain
- * @list: Chain to be counted
- *
- * Returns the number of TLVs stored in the passed chain.
- *
- */
-int aim_counttlvchain(aim_tlvlist_t **list)
-{
-	aim_tlvlist_t *cur;
-	int count;
-
-	if (!list || !*list) {
-		return 0;
-	}
-
-	for (cur = *list, count = 0; cur; cur = cur->next) {
-		count++;
-	}
-
-	return count;
-}
-
-/**
- * aim_sizetlvchain - Count the number of bytes in a TLV chain
- * @list: Chain to be sized
- *
- * Returns the number of bytes that would be needed to
- * write the passed TLV chain to a data buffer.
- *
- */
-int aim_sizetlvchain(aim_tlvlist_t **list)
-{
-	aim_tlvlist_t *cur;
-	int size;
-
-	if (!list || !*list) {
-		return 0;
-	}
-
-	for (cur = *list, size = 0; cur; cur = cur->next) {
-		size += (4 + cur->tlv->length);
-	}
-
-	return size;
-}
-
-/**
- * aim_addtlvtochain_str - Add a string to a TLV chain
- * @list: Designation chain (%NULL pointer if empty)
- * @type: TLV type
- * @str: String to add
- * @len: Length of string to add (not including %NULL)
- *
- * Adds the passed string as a TLV element of the passed type
- * to the TLV chain.
- *
- */
-int aim_addtlvtochain_raw(aim_tlvlist_t **list, const guint16 t, const guint16 l, const guint8 *v)
-{
-	aim_tlvlist_t *newtlv, *cur;
-
-	if (!list) {
-		return 0;
-	}
-
-	if (!(newtlv = g_new0(aim_tlvlist_t, 1))) {
-		return 0;
-	}
-
-	if (!(newtlv->tlv = g_new0(aim_tlv_t, 1))) {
-		g_free(newtlv);
-		return 0;
-	}
-	newtlv->tlv->type = t;
-	if ((newtlv->tlv->length = l)) {
-		newtlv->tlv->value = (guint8 *) g_malloc(newtlv->tlv->length);
-		memcpy(newtlv->tlv->value, v, newtlv->tlv->length);
-	}
-
-	if (!*list) {
-		*list = newtlv;
-	} else {
-		for (cur = *list; cur->next; cur = cur->next) {
-			;
-		}
-		cur->next = newtlv;
-	}
-
-	return newtlv->tlv->length;
-}
-
-/**
- * aim_addtlvtochain8 - Add a 8bit integer to a TLV chain
- * @list: Destination chain
- * @type: TLV type to add
- * @val: Value to add
- *
- * Adds a one-byte unsigned integer to a TLV chain.
- *
- */
-int aim_addtlvtochain8(aim_tlvlist_t **list, const guint16 t, const guint8 v)
-{
-	guint8 v8[1];
-
-	(void) aimutil_put8(v8, v);
-
-	return aim_addtlvtochain_raw(list, t, 1, v8);
-}
-
-/**
- * aim_addtlvtochain16 - Add a 16bit integer to a TLV chain
- * @list: Destination chain
- * @type: TLV type to add
- * @val: Value to add
- *
- * Adds a two-byte unsigned integer to a TLV chain.
- *
- */
-int aim_addtlvtochain16(aim_tlvlist_t **list, const guint16 t, const guint16 v)
-{
-	guint8 v16[2];
-
-	(void) aimutil_put16(v16, v);
-
-	return aim_addtlvtochain_raw(list, t, 2, v16);
-}
-
-/**
- * aim_addtlvtochain32 - Add a 32bit integer to a TLV chain
- * @list: Destination chain
- * @type: TLV type to add
- * @val: Value to add
- *
- * Adds a four-byte unsigned integer to a TLV chain.
- *
- */
-int aim_addtlvtochain32(aim_tlvlist_t **list, const guint16 t, const guint32 v)
-{
-	guint8 v32[4];
-
-	(void) aimutil_put32(v32, v);
-
-	return aim_addtlvtochain_raw(list, t, 4, v32);
-}
-
-/**
- * aim_addtlvtochain_caps - Add a capability block to a TLV chain
- * @list: Destination chain
- * @type: TLV type to add
- * @caps: Bitfield of capability flags to send
- *
- * Adds a block of capability blocks to a TLV chain. The bitfield
- * passed in should be a bitwise %OR of any of the %AIM_CAPS constants:
- *
- */
-int aim_addtlvtochain_caps(aim_tlvlist_t **list, const guint16 t, const guint32 caps)
-{
-	guint8 buf[16 * 16]; /* XXX icky fixed length buffer */
-	aim_bstream_t bs;
-
-	if (!caps) {
-		return 0; /* nothing there anyway */
-
-	}
-	aim_bstream_init(&bs, buf, sizeof(buf));
-
-	aim_putcap(&bs, caps);
-
-	return aim_addtlvtochain_raw(list, t, aim_bstream_curpos(&bs), buf);
-}
-
-/**
- * aim_addtlvtochain_noval - Add a blank TLV to a TLV chain
- * @list: Destination chain
- * @type: TLV type to add
- *
- * Adds a TLV with a zero length to a TLV chain.
- *
- */
-int aim_addtlvtochain_noval(aim_tlvlist_t **list, const guint16 t)
-{
-	return aim_addtlvtochain_raw(list, t, 0, NULL);
-}
-
-/*
- * Note that the inner TLV chain will not be modifiable as a tlvchain once
- * it is written using this.  Or rather, it can be, but updates won't be
- * made to this.
- *
- * XXX should probably support sublists for real.
- *
- * This is so neat.
- *
- */
-int aim_addtlvtochain_frozentlvlist(aim_tlvlist_t **list, guint16 type, aim_tlvlist_t **tl)
-{
-	guint8 *buf;
-	int buflen;
-	aim_bstream_t bs;
-
-	buflen = aim_sizetlvchain(tl);
-
-	if (buflen <= 0) {
-		return 0;
-	}
-
-	if (!(buf = g_malloc(buflen))) {
-		return 0;
-	}
-
-	aim_bstream_init(&bs, buf, buflen);
-
-	aim_writetlvchain(&bs, tl);
-
-	aim_addtlvtochain_raw(list, type, aim_bstream_curpos(&bs), buf);
-
-	g_free(buf);
-
-	return buflen;
-}
-
-int aim_addtlvtochain_chatroom(aim_tlvlist_t **list, guint16 type, guint16 exchange, const char *roomname,
-                               guint16 instance)
-{
-	guint8 *buf;
-	int buflen;
-	aim_bstream_t bs;
-
-	buflen = 2 + 1 + strlen(roomname) + 2;
-
-	if (!(buf = g_malloc(buflen))) {
-		return 0;
-	}
-
-	aim_bstream_init(&bs, buf, buflen);
-
-	aimbs_put16(&bs, exchange);
-	aimbs_put8(&bs, strlen(roomname));
-	aimbs_putraw(&bs, (guint8 *) roomname, strlen(roomname));
-	aimbs_put16(&bs, instance);
-
-	aim_addtlvtochain_raw(list, type, aim_bstream_curpos(&bs), buf);
-
-	g_free(buf);
-
-	return 0;
-}
-
-/**
- * aim_writetlvchain - Write a TLV chain into a data buffer.
- * @buf: Destination buffer
- * @buflen: Maximum number of bytes that will be written to buffer
- * @list: Source TLV chain
- *
- * Copies a TLV chain into a raw data buffer, writing only the number
- * of bytes specified. This operation does not free the chain;
- * aim_freetlvchain() must still be called to free up the memory used
- * by the chain structures.
- *
- * XXX clean this up, make better use of bstreams
- */
-int aim_writetlvchain(aim_bstream_t *bs, aim_tlvlist_t **list)
-{
-	int goodbuflen;
-	aim_tlvlist_t *cur;
-
-	/* do an initial run to test total length */
-	for (cur = *list, goodbuflen = 0; cur; cur = cur->next) {
-		goodbuflen += 2 + 2; /* type + len */
-		goodbuflen += cur->tlv->length;
-	}
-
-	if (goodbuflen > aim_bstream_empty(bs)) {
-		return 0; /* not enough buffer */
-
-	}
-	/* do the real write-out */
-	for (cur = *list; cur; cur = cur->next) {
-		aimbs_put16(bs, cur->tlv->type);
-		aimbs_put16(bs, cur->tlv->length);
-		if (cur->tlv->length) {
-			aimbs_putraw(bs, cur->tlv->value, cur->tlv->length);
-		}
-	}
-
-	return 1; /* XXX this is a nonsensical return */
-}
-
-
-/**
- * aim_gettlv - Grab the Nth TLV of type type in the TLV list list.
- * @list: Source chain
- * @type: Requested TLV type
- * @nth: Index of TLV of type to get
- *
- * Returns a pointer to an aim_tlv_t of the specified type;
- * %NULL on error.  The @nth parameter is specified starting at %1.
- * In most cases, there will be no more than one TLV of any type
- * in a chain.
- *
- */
-aim_tlv_t *aim_gettlv(aim_tlvlist_t *list, const guint16 t, const int n)
-{
-	aim_tlvlist_t *cur;
-	int i;
-
-	for (cur = list, i = 0; cur; cur = cur->next) {
-		if (cur && cur->tlv) {
-			if (cur->tlv->type == t) {
-				i++;
-			}
-			if (i >= n) {
-				return cur->tlv;
-			}
-		}
-	}
-
-	return NULL;
-}
-
-/**
- * aim_gettlv_str - Retrieve the Nth TLV in chain as a string.
- * @list: Source TLV chain
- * @type: TLV type to search for
- * @nth: Index of TLV to return
- *
- * Same as aim_gettlv(), except that the return value is a %NULL-
- * terminated string instead of an aim_tlv_t.  This is a
- * dynamic buffer and must be freed by the caller.
- *
- */
-char *aim_gettlv_str(aim_tlvlist_t *list, const guint16 t, const int n)
-{
-	aim_tlv_t *tlv;
-	char *newstr;
-
-	if (!(tlv = aim_gettlv(list, t, n))) {
-		return NULL;
-	}
-
-	newstr = (char *) g_malloc(tlv->length + 1);
-	memcpy(newstr, tlv->value, tlv->length);
-	*(newstr + tlv->length) = '\0';
-
-	return newstr;
-}
-
-/**
- * aim_gettlv8 - Retrieve the Nth TLV in chain as a 8bit integer.
- * @list: Source TLV chain
- * @type: TLV type to search for
- * @nth: Index of TLV to return
- *
- * Same as aim_gettlv(), except that the return value is a
- * 8bit integer instead of an aim_tlv_t.
- *
- */
-guint8 aim_gettlv8(aim_tlvlist_t *list, const guint16 t, const int n)
-{
-	aim_tlv_t *tlv;
-
-	if (!(tlv = aim_gettlv(list, t, n))) {
-		return 0; /* erm */
-	}
-	return aimutil_get8(tlv->value);
-}
-
-/**
- * aim_gettlv16 - Retrieve the Nth TLV in chain as a 16bit integer.
- * @list: Source TLV chain
- * @type: TLV type to search for
- * @nth: Index of TLV to return
- *
- * Same as aim_gettlv(), except that the return value is a
- * 16bit integer instead of an aim_tlv_t.
- *
- */
-guint16 aim_gettlv16(aim_tlvlist_t *list, const guint16 t, const int n)
-{
-	aim_tlv_t *tlv;
-
-	if (!(tlv = aim_gettlv(list, t, n))) {
-		return 0; /* erm */
-	}
-	return aimutil_get16(tlv->value);
-}
-
-/**
- * aim_gettlv32 - Retrieve the Nth TLV in chain as a 32bit integer.
- * @list: Source TLV chain
- * @type: TLV type to search for
- * @nth: Index of TLV to return
- *
- * Same as aim_gettlv(), except that the return value is a
- * 32bit integer instead of an aim_tlv_t.
- *
- */
-guint32 aim_gettlv32(aim_tlvlist_t *list, const guint16 t, const int n)
-{
-	aim_tlv_t *tlv;
-
-	if (!(tlv = aim_gettlv(list, t, n))) {
-		return 0; /* erm */
-	}
-	return aimutil_get32(tlv->value);
-}
-
-#if 0
-/**
- * aim_puttlv_8 - Write a one-byte TLV.
- * @buf: Destination buffer
- * @t: TLV type
- * @v: Value
- *
- * Writes a TLV with a one-byte integer value portion.
- *
- */
-int aim_puttlv_8(guint8 *buf, const guint16 t, const guint8 v)
-{
-	guint8 v8[1];
-
-	aimutil_put8(v8, v);
-
-	return aim_puttlv_raw(buf, t, 1, v8);
-}
-
-/**
- * aim_puttlv_16 - Write a two-byte TLV.
- * @buf: Destination buffer
- * @t: TLV type
- * @v: Value
- *
- * Writes a TLV with a two-byte integer value portion.
- *
- */
-int aim_puttlv_16(guint8 *buf, const guint16 t, const guint16 v)
-{
-	guint8 v16[2];
-
-	aimutil_put16(v16, v);
-
-	return aim_puttlv_raw(buf, t, 2, v16);
-}
-
-
-/**
- * aim_puttlv_32 - Write a four-byte TLV.
- * @buf: Destination buffer
- * @t: TLV type
- * @v: Value
- *
- * Writes a TLV with a four-byte integer value portion.
- *
- */
-int aim_puttlv_32(guint8 *buf, const guint16 t, const guint32 v)
-{
-	guint8 v32[4];
-
-	aimutil_put32(v32, v);
-
-	return aim_puttlv_raw(buf, t, 4, v32);
-}
-
-/**
- * aim_puttlv_raw - Write a raw TLV.
- * @buf: Destination buffer
- * @t: TLV type
- * @l: Length of string
- * @v: String to write
- *
- * Writes a TLV with a raw value portion.  (Only the first @l
- * bytes of the passed buffer will be written, which should not
- * include a terminating NULL.)
- *
- */
-int aim_puttlv_raw(guint8 *buf, const guint16 t, const guint16 l, const guint8 *v)
-{
-	int i;
-
-	i = aimutil_put16(buf, t);
-	i += aimutil_put16(buf + i, l);
-	if (l) {
-		memcpy(buf + i, v, l);
-	}
-	i += l;
-
-	return i;
-}
-#endif
-
Index: protocols/oscar/txqueue.c
===================================================================
--- protocols/oscar/txqueue.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ 	(revision )
@@ -1,373 +1,0 @@
-/*
- *  aim_txqueue.c
- *
- * Herein lies all the mangement routines for the transmit (Tx) queue.
- *
- */
-
-#include <aim.h>
-#include "im.h"
-
-#include <sys/socket.h>
-
-/*
- * Allocate a new tx frame.
- *
- * This is more for looks than anything else.
- *
- * Right now, that is.  If/when we implement a pool of transmit
- * frames, this will become the request-an-unused-frame part.
- *
- * framing = AIM_FRAMETYPE_OFT/FLAP
- * chan = channel for FLAP, hdrtype for OFT
- *
- */
-aim_frame_t *aim_tx_new(aim_session_t *sess, aim_conn_t *conn, guint8 framing, guint8 chan, int datalen)
-{
-	aim_frame_t *fr;
-
-	if (!conn) {
-		imcb_error(sess->aux_data, "no connection specified");
-		return NULL;
-	}
-
-	if (!(fr = (aim_frame_t *) g_new0(aim_frame_t, 1))) {
-		return NULL;
-	}
-
-	fr->conn = conn;
-
-	fr->hdrtype = framing;
-
-	if (fr->hdrtype == AIM_FRAMETYPE_FLAP) {
-
-		fr->hdr.flap.type = chan;
-
-	} else {
-		imcb_error(sess->aux_data, "unknown framing");
-	}
-
-	if (datalen > 0) {
-		guint8 *data;
-
-		if (!(data = (unsigned char *) g_malloc(datalen))) {
-			aim_frame_destroy(fr);
-			return NULL;
-		}
-
-		aim_bstream_init(&fr->data, data, datalen);
-	}
-
-	return fr;
-}
-
-/*
- * aim_tx_enqeue__queuebased()
- *
- * The overall purpose here is to enqueue the passed in command struct
- * into the outgoing (tx) queue.  Basically...
- *   1) Make a scope-irrelevant copy of the struct
- *   3) Mark as not-sent-yet
- *   4) Enqueue the struct into the list
- *   6) Return
- *
- * Note that this is only used when doing queue-based transmitting;
- * that is, when sess->tx_enqueue is set to &aim_tx_enqueue__queuebased.
- *
- */
-static int aim_tx_enqueue__queuebased(aim_session_t *sess, aim_frame_t *fr)
-{
-
-	if (!fr->conn) {
-		imcb_error(sess->aux_data, "Warning: enqueueing packet with no connection");
-		fr->conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
-	}
-
-	if (fr->hdrtype == AIM_FRAMETYPE_FLAP) {
-		/* assign seqnum -- XXX should really not assign until hardxmit */
-		fr->hdr.flap.seqnum = aim_get_next_txseqnum(fr->conn);
-	}
-
-	fr->handled = 0; /* not sent yet */
-
-	/* see overhead note in aim_rxqueue counterpart */
-	if (!sess->queue_outgoing) {
-		sess->queue_outgoing = fr;
-	} else {
-		aim_frame_t *cur;
-
-		for (cur = sess->queue_outgoing; cur->next; cur = cur->next) {
-			;
-		}
-		cur->next = fr;
-	}
-
-	return 0;
-}
-
-/*
- * aim_tx_enqueue__immediate()
- *
- * Parallel to aim_tx_enqueue__queuebased, however, this bypasses
- * the whole queue mess when you want immediate writes to happen.
- *
- * Basically the same as its __queuebased couterpart, however
- * instead of doing a list append, it just calls aim_tx_sendframe()
- * right here.
- *
- */
-static int aim_tx_enqueue__immediate(aim_session_t *sess, aim_frame_t *fr)
-{
-
-	if (!fr->conn) {
-		imcb_error(sess->aux_data, "packet has no connection");
-		aim_frame_destroy(fr);
-		return 0;
-	}
-
-	if (fr->hdrtype == AIM_FRAMETYPE_FLAP) {
-		fr->hdr.flap.seqnum = aim_get_next_txseqnum(fr->conn);
-	}
-
-	fr->handled = 0; /* not sent yet */
-
-	aim_tx_sendframe(sess, fr);
-
-	aim_frame_destroy(fr);
-
-	return 0;
-}
-
-int aim_tx_setenqueue(aim_session_t *sess, int what, int (*func)(aim_session_t *, aim_frame_t *))
-{
-
-	if (what == AIM_TX_QUEUED) {
-		sess->tx_enqueue = &aim_tx_enqueue__queuebased;
-	} else if (what == AIM_TX_IMMEDIATE) {
-		sess->tx_enqueue = &aim_tx_enqueue__immediate;
-	} else if (what == AIM_TX_USER) {
-		if (!func) {
-			return -EINVAL;
-		}
-		sess->tx_enqueue = func;
-	} else {
-		return -EINVAL; /* unknown action */
-
-	}
-	return 0;
-}
-
-int aim_tx_enqueue(aim_session_t *sess, aim_frame_t *fr)
-{
-
-	/*
-	 * If we want to send a connection thats inprogress, we have to force
-	 * them to use the queue based version. Otherwise, use whatever they
-	 * want.
-	 */
-	if (fr && fr->conn &&
-	    (fr->conn->status & AIM_CONN_STATUS_INPROGRESS)) {
-		return aim_tx_enqueue__queuebased(sess, fr);
-	}
-
-	return (*sess->tx_enqueue)(sess, fr);
-}
-
-/*
- *  aim_get_next_txseqnum()
- *
- *   This increments the tx command count, and returns the seqnum
- *   that should be stamped on the next FLAP packet sent.  This is
- *   normally called during the final step of packet preparation
- *   before enqueuement (in aim_tx_enqueue()).
- *
- */
-flap_seqnum_t aim_get_next_txseqnum(aim_conn_t *conn)
-{
-	flap_seqnum_t ret;
-
-	ret = ++conn->seqnum;
-
-	return ret;
-}
-
-static int aim_send(int fd, const void *buf, size_t count)
-{
-	int left, cur;
-
-	for (cur = 0, left = count; left; ) {
-		int ret;
-
-		ret = send(fd, ((unsigned char *) buf) + cur, left, 0);
-		if (ret == -1) {
-			return -1;
-		} else if (ret == 0) {
-			return cur;
-		}
-
-		cur += ret;
-		left -= ret;
-	}
-
-	return cur;
-}
-
-static int aim_bstream_send(aim_bstream_t *bs, aim_conn_t *conn, size_t count)
-{
-	int wrote = 0;
-
-	if (!bs || !conn || (count < 0)) {
-		return -EINVAL;
-	}
-
-	if (count > aim_bstream_empty(bs)) {
-		count = aim_bstream_empty(bs); /* truncate to remaining space */
-
-	}
-	if (count) {
-		if (count - wrote) {
-			wrote = wrote + aim_send(conn->fd, bs->data + bs->offset + wrote, count - wrote);
-		}
-
-	}
-
-	bs->offset += wrote;
-
-	return wrote;
-}
-
-static int sendframe_flap(aim_session_t *sess, aim_frame_t *fr)
-{
-	aim_bstream_t obs;
-	guint8 *obs_raw;
-	int payloadlen, err = 0, obslen;
-
-	payloadlen = aim_bstream_curpos(&fr->data);
-
-	if (!(obs_raw = g_malloc(6 + payloadlen))) {
-		return -ENOMEM;
-	}
-
-	aim_bstream_init(&obs, obs_raw, 6 + payloadlen);
-
-	/* FLAP header */
-	aimbs_put8(&obs, 0x2a);
-	aimbs_put8(&obs, fr->hdr.flap.type);
-	aimbs_put16(&obs, fr->hdr.flap.seqnum);
-	aimbs_put16(&obs, payloadlen);
-
-	/* payload */
-	aim_bstream_rewind(&fr->data);
-	aimbs_putbs(&obs, &fr->data, payloadlen);
-
-	obslen = aim_bstream_curpos(&obs);
-	aim_bstream_rewind(&obs);
-	if (aim_bstream_send(&obs, fr->conn, obslen) != obslen) {
-		err = -errno;
-	}
-
-	g_free(obs_raw); /* XXX aim_bstream_free */
-
-	fr->handled = 1;
-	fr->conn->lastactivity = time(NULL);
-
-	return err;
-}
-
-int aim_tx_sendframe(aim_session_t *sess, aim_frame_t *fr)
-{
-	if (fr->hdrtype == AIM_FRAMETYPE_FLAP) {
-		return sendframe_flap(sess, fr);
-	}
-	return -1;
-}
-
-int aim_tx_flushqueue(aim_session_t *sess)
-{
-	aim_frame_t *cur;
-
-	for (cur = sess->queue_outgoing; cur; cur = cur->next) {
-
-		if (cur->handled) {
-			continue; /* already been sent */
-
-		}
-		if (cur->conn && (cur->conn->status & AIM_CONN_STATUS_INPROGRESS)) {
-			continue;
-		}
-
-		/*
-		 * And now for the meager attempt to force transmit
-		 * latency and avoid missed messages.
-		 */
-		if ((cur->conn->lastactivity + cur->conn->forcedlatency) >= time(NULL)) {
-			/*
-			 * XXX should be a break! we dont want to block the
-			 * upper layers
-			 *
-			 * XXX or better, just do this right.
-			 *
-			 */
-			sleep((cur->conn->lastactivity + cur->conn->forcedlatency) - time(NULL));
-		}
-
-		/* XXX this should call the custom "queuing" function!! */
-		aim_tx_sendframe(sess, cur);
-	}
-
-	/* purge sent commands from queue */
-	aim_tx_purgequeue(sess);
-
-	return 0;
-}
-
-/*
- *  aim_tx_purgequeue()
- *
- *  This is responsable for removing sent commands from the transmit
- *  queue. This is not a required operation, but it of course helps
- *  reduce memory footprint at run time!
- *
- */
-void aim_tx_purgequeue(aim_session_t *sess)
-{
-	aim_frame_t *cur, **prev;
-
-	for (prev = &sess->queue_outgoing; (cur = *prev); ) {
-
-		if (cur->handled) {
-			*prev = cur->next;
-
-			aim_frame_destroy(cur);
-
-		} else {
-			prev = &cur->next;
-		}
-	}
-
-	return;
-}
-
-/**
- * aim_tx_cleanqueue - get rid of packets waiting for tx on a dying conn
- * @sess: session
- * @conn: connection that's dying
- *
- * for now this simply marks all packets as sent and lets them
- * disappear without warning.
- *
- */
-void aim_tx_cleanqueue(aim_session_t *sess, aim_conn_t *conn)
-{
-	aim_frame_t *cur;
-
-	for (cur = sess->queue_outgoing; cur; cur = cur->next) {
-		if (cur->conn == conn) {
-			cur->handled = 1;
-		}
-	}
-
-	return;
-}
-
-
Index: protocols/purple/purple.c
===================================================================
--- protocols/purple/purple.c	(revision 0b1448f070917daf4966097a06b47fc4b2ce0c92)
+++ protocols/purple/purple.c	(revision e5d2c5607310ef9669a051a1b93e019319495955)
@@ -107,15 +107,4 @@
 }
 
-static char *purple_get_account_prpl_id(account_t *acc)
-{
-	/* "oscar" is how non-purple bitlbee calls it,
-	 * and it might be icq or aim, depending on the username */
-	if (g_strcmp0(acc->prpl->name, "oscar") == 0) {
-		return (g_ascii_isdigit(acc->user[0])) ? "prpl-icq" : "prpl-aim";
-	}
-
-	return acc->prpl->data;
-}
-
 static gboolean purple_account_should_set_nick(account_t *acc)
 {
@@ -127,5 +116,4 @@
 		"prpl-hangouts",
 		"prpl-eionrobb-funyahoo-plusplus",
-		"prpl-icq",
 		"prpl-line",
 		NULL,
@@ -144,5 +132,5 @@
 static void purple_init(account_t *acc)
 {
-	char *prpl_id = purple_get_account_prpl_id(acc);
+	char *prpl_id = acc->prpl->data;
 	PurplePlugin *prpl = purple_plugins_find_with_id(prpl_id);
 	PurplePluginProtocolInfo *pi = prpl->info->extra_info;
@@ -399,5 +387,5 @@
 
 	ic->proto_data = pd = g_new0(struct purple_data, 1);
-	pd->account = purple_account_new(acc->user, purple_get_account_prpl_id(acc));
+	pd->account = purple_account_new(acc->user, acc->prpl->data);
 	pd->input_requests = g_hash_table_new_full(g_direct_hash, g_direct_equal,
 	                                           NULL, g_free);
@@ -1957,14 +1945,4 @@
 		g_string_append_printf(help, "\n* %s (%s)", ret->name, prot->info->name);
 
-		/* libpurple doesn't define a protocol called OSCAR, but we
-		   need it to be compatible with normal BitlBee. */
-		if (g_strcasecmp(prot->info->id, "prpl-aim") == 0) {
-			ret = g_memdup(&funcs, sizeof(funcs));
-			ret->name = "oscar";
-			/* purple_get_account_prpl_id() determines the actual protocol ID (icq/aim) */
-			ret->data = NULL;
-			register_protocol(ret);
-		}
-
 		info = g_new0(struct plugin_info, 1);
 		info->abiver = BITLBEE_ABI_VERSION_CODE;
