explicit merge of '87854ccfae544467c988edbac854c1ae2018eed4' soc.2007.msimprpl

Mon, 18 Jun 2007 01:48:35 +0000

author
Jeff Connelly <jeff2@soc.pidgin.im>
date
Mon, 18 Jun 2007 01:48:35 +0000
branch
soc.2007.msimprpl
changeset 17977
328f7ae1714b
parent 17751
87854ccfae54 (diff)
parent 17976
4fe92c2fa5af (current diff)
child 17979
a65747e01794

explicit merge of '87854ccfae544467c988edbac854c1ae2018eed4'
and '4fe92c2fa5afd77565c3b27aba6c2b9674a88322'

COPYRIGHT file | annotate | diff | comparison | revisions
configure.ac file | annotate | diff | comparison | revisions
libpurple/cipher.c file | annotate | diff | comparison | revisions
libpurple/protocols/bonjour/dns_sd.c file | annotate | diff | comparison | revisions
libpurple/protocols/bonjour/dns_sd.h file | annotate | diff | comparison | revisions
libpurple/protocols/bonjour/mdns_howl.c file | annotate | diff | comparison | revisions
libpurple/protocols/bonjour/mdns_howl.h file | annotate | diff | comparison | revisions
pidgin/pixmaps/emotes/default/22/default.theme.in file | annotate | diff | comparison | revisions
pidgin/pixmaps/emotes/default/22/theme file | annotate | diff | comparison | revisions
pidgin/pixmaps/emotes/none/none.theme.in file | annotate | diff | comparison | revisions
pidgin/pixmaps/emotes/none/theme file | annotate | diff | comparison | revisions
po/POTFILES.in file | annotate | diff | comparison | revisions
--- a/.mtn-ignore	Thu Jun 14 19:48:48 2007 +0000
+++ b/.mtn-ignore	Mon Jun 18 01:48:35 2007 +0000
@@ -5,12 +5,14 @@
 .*/perl/common/blib.*
 .*/perl/common/pm_to_blib$
 .*\.bs$
+.*\.def$
 .*\.dll$
 .*\.exe$
 intltool-.*
 Doxyfile$
 aclocal.m4
 compile
+config.cache
 config.guess
 config.h$
 config.h.in
@@ -30,7 +32,9 @@
 pidgin.spec$
 pidgin-.*.tar.gz
 pidgin-.*.tar.bz2
-pidgin/pidgin
+pidgin/pidgin$
+pidgin/pixmaps/emotes/default/22/theme
+pidgin/pixmaps/emotes/none/theme
 pidgin/plugins/musicmessaging/music-messaging-bindings.c
 pidgin/plugins/perl/common/Makefile.PL$
 pidgin/win32/pidgin_dll_rc.rc$
@@ -50,7 +54,7 @@
 libpurple/purple-client-bindings.h
 libpurple/purple-client-example
 libpurple/tests/check_libpurple
-libpurple/version.h
+libpurple/version.h$
 libpurple/win32/libpurplerc.rc$
 libtool
 local.mak
--- a/COPYRIGHT	Thu Jun 14 19:48:48 2007 +0000
+++ b/COPYRIGHT	Mon Jun 18 01:48:35 2007 +0000
@@ -8,6 +8,7 @@
 Dave Ahlswede
 Manuel Amador
 Matt Amato
+Elliott Sales de Andrade
 Geoffrey Antos
 Daniel Atallah
 Paul Aurich
@@ -88,6 +89,7 @@
 Jeramey Crawford
 Michael Culbertson
 Steven Danna
+Chris Davies
 Martijn Dekker
 Vinicius Depizzol
 Philip Derrin
@@ -129,6 +131,7 @@
 Decklin Foster
 Francesco Fracassi
 Adam Fritzler
+Takao Fujiwara
 Max G.
 François Gagné
 Andrew Gaul
@@ -149,6 +152,7 @@
 Casey Harkins
 Andy Harrison
 Andrew Hart (arhart)
+Rene Hausleitner
 G. Sumner Hayes
 Michael R. Head
 Nick Hebner
@@ -222,6 +226,7 @@
 Lalo Martins
 John Matthews
 Simo Mattila
+Michal Matyska
 Ryan McCabe
 Peter McCurdy
 Kurt McKee
@@ -334,8 +339,10 @@
 Richard Stellingwerff
 Charlie Stockman
 David Stoddard
+Oleg Sukhodolsky
 Sun Microsystems
 Mårten Svantesson (fursten)
+Amir Szekely (kichik)
 Robert T.
 Greg Taeger
 Peter Tang
--- a/ChangeLog	Thu Jun 14 19:48:48 2007 +0000
+++ b/ChangeLog	Mon Jun 18 01:48:35 2007 +0000
@@ -1,5 +1,35 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
+version 2.0.2 (06/14/2007):
+	Pidgin:
+	* Added a custom conversation font option to preferences
+	* Fixed smiley ordering in the insert smiley popup to be more intuitive
+	* Conversation->More menu items work for Chats as well as Buddies,
+	  including those not on your buddy list
+	* newline plugin should work better with conversation colors plugin now
+	* Get Info on users now provides immediate feedback that something is
+	  happening
+	* Aliasing a buddy will not be interrupted by other buddy list activity
+	* Using the -l option to log in to a specific account works better
+
+	libpurple:
+	* Moving an ICQ buddy from one group to another no longer
+	  re-requests authorization from that person (Rene Hausleitner)
+	* Added nullprpl, an example protocol plugin (Ryan Barrett)
+	* Fixed SOCKS5 bug which caused Jabber file receiving to fail
+	* Remove MSN's random "Authorization Failed" dialogs
+	* Fix MSN to correctly detect incorrect passwords and disable the account
+	* Get User Info on MSN is now more reliable & accurate
+	* Updated SILC protocol to support SILC Toolkit 1.1 (Pekka Riikonen)
+	* Fix for some QQ authentication problems
+	* Fix for building on FreeBSD
+	* Prevent "Logged in:" times for AIM buddies being ridiculously high
+	* Updates and fixes to Bonjour support
+	* Improve ICQ encoding support for some non-latin languages
+
+	Finch:
+	* Auto account reconnecting
+
 version 2.0.1 (05/24/2007):
 	* Buddy list update speedups when buddy icons are not being
 	  displayed.  (Scott Wolchok)
--- a/ChangeLog.API	Thu Jun 14 19:48:48 2007 +0000
+++ b/ChangeLog.API	Mon Jun 18 01:48:35 2007 +0000
@@ -1,5 +1,11 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
+version 2.0.2 (6/14/2007):
+	Pidgin:
+		Deprecated:
+		* pidgin_dialogs_alias_contact:  This will be removed in 3.0.0
+		  unless there is sufficient demand to keep it.
+
 version 2.0.0 (5/3/2007):
 	Please note all functions, defines, and data structures have been
 	re-namespaced to match the new names of Pidgin, Finch, and libpurple.
--- a/ChangeLog.win32	Thu Jun 14 19:48:48 2007 +0000
+++ b/ChangeLog.win32	Mon Jun 18 01:48:35 2007 +0000
@@ -1,4 +1,7 @@
-version 2.0.1 (??/??/????):
+version 2.0.2 (6/14/2007):
+	* Add Bonjour protocol support thanks to Chris Davies. This requires
+	  Apple Bonjour for Windows from:
+	  http://www.apple.com/support/downloads/bonjourforwindows.html
 
 version 2.0.0 (5/3/2007):
 	* URI Handler support added via `pidgin.exe --protocolhandler=`
--- a/NEWS	Thu Jun 14 19:48:48 2007 +0000
+++ b/NEWS	Mon Jun 18 01:48:35 2007 +0000
@@ -1,5 +1,18 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
+2.0.2 (6/14/2007):
+	Sean: Another big maintenance release. Again, about 100 tickets were
+	resolved in this release, and they keep coming in. Lots of bug fixes,
+	some minor icon adjustements, hopefully we addressed some ICQ
+	internationalization issues, and support for Bonjour on Windows!
+	Our next release will be 2.1.0, and will come with some great new
+	features.
+
+	Stu: I think we're gradually getting the hang of this 3 week thing
+	again. This release includes yet more bug fixes. I'd also like to
+	specifically thank Pekka Riikonen for the patch to enable using SILC
+	Toolkit 1.1 with Pidgin/libpurple that is included in this release.
+
 2.0.1 (5/24/2007):
 	Sean: 2.0.1! Three weeks later, as scheduled! It is so nice to have
 	regular, frequent, releases again! This is a bugfix release; We have
--- a/config.h.mingw	Thu Jun 14 19:48:48 2007 +0000
+++ b/config.h.mingw	Mon Jun 18 01:48:35 2007 +0000
@@ -306,7 +306,7 @@
 /* #undef HAVE_TZNAME */
 
 /* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
+/*#define HAVE_UNISTD_H 1*/
 
 /* Define to 1 if you have the `vprintf' function. */
 #define HAVE_VPRINTF 1
@@ -344,9 +344,6 @@
 /* Define to the version of this package. */
 /* #define PACKAGE_VERSION "2.0.0dev" */
 
-/* Define to make assertions fatal (useful for debugging). */
-/* #define PURPLE_FATAL_ASSERTS 1 */
-
 /* Define if plugins are enabled. */
 #define PURPLE_PLUGINS 1
 
--- a/configure.ac	Thu Jun 14 19:48:48 2007 +0000
+++ b/configure.ac	Mon Jun 18 01:48:35 2007 +0000
@@ -46,7 +46,7 @@
 m4_define([purple_lt_current], [0])
 m4_define([purple_major_version], [2])
 m4_define([purple_minor_version], [0])
-m4_define([purple_micro_version], [1])
+m4_define([purple_micro_version], [2])
 m4_define([purple_version_suffix], [])
 m4_define([purple_version],
           [purple_major_version.purple_minor_version.purple_micro_version])
@@ -55,7 +55,7 @@
 m4_define([gnt_lt_current], [0])
 m4_define([gnt_major_version], [1])
 m4_define([gnt_minor_version], [0])
-m4_define([gnt_micro_version], [1])
+m4_define([gnt_micro_version], [2])
 m4_define([gnt_version_suffix], [])
 m4_define([gnt_version],
           [gnt_major_version.gnt_minor_version.gnt_micro_version])
@@ -142,7 +142,7 @@
 dnl If we don't have msgfmt, then po/ is going to fail -- ensure that
 dnl AM_GLIB_GNU_GETTEXT found it.
 
-if test x$MSGFMT = xno -o x$GMSGFMT = x
+if test x$MSGFMT = xno
 then
 	AC_ERROR([
 
@@ -569,14 +569,15 @@
 AC_ARG_ENABLE(gstreamer,
 	[AC_HELP_STRING([--disable-gstreamer], [compile without GStreamer audio support])],
 	enable_gst="$enableval", enable_gst="yes")
-PKG_CHECK_MODULES(GSTREAMER, [gstreamer-0.10], , [
-	AC_MSG_RESULT(no)
-	enable_gst="no"
-])
 if test "x$enable_gst" != "xno"; then
-	AC_DEFINE(USE_GSTREAMER, 1, [Use GStreamer for playing sounds])
-	AC_SUBST(GSTREAMER_CFLAGS)
-	AC_SUBST(GSTREAMER_LIBS)
+	PKG_CHECK_MODULES(GSTREAMER, [gstreamer-0.10], [
+		AC_DEFINE(USE_GSTREAMER, 1, [Use GStreamer for playing sounds])
+		AC_SUBST(GSTREAMER_CFLAGS)
+		AC_SUBST(GSTREAMER_LIBS)
+	], [
+		AC_MSG_RESULT(no)
+		enable_gst="no"
+	])
 fi
 
 dnl #######################################################################
@@ -646,13 +647,14 @@
 AC_ARG_WITH(silc-libs, [AC_HELP_STRING([--with-silc-libs=DIR], [compile the SILC plugin against the SILC libs in DIR])], [ac_silc_libs="$withval"], [ac_silc_libs="no"])
 SILC_CFLAGS=""
 SILC_LIBS=""
+have_silc="no"
 if test -n "$with_silc_includes" || test -n "$with_silc_libs"; then
 	silc_manual_check="yes"
 else
 	silc_manual_check="no"
 fi
 if test "x$silc_manual_check" = "xno"; then
-	PKG_CHECK_MODULES(SILC, silcclient, [
+	PKG_CHECK_MODULES(SILC, [silcclient >= 1.1], [
 		have_silc="yes"
 		silcincludes="yes"
 		silcclient="yes"
@@ -660,16 +662,26 @@
 		AC_MSG_RESULT(no)
 		have_silc="no"
 	])
-	dnl If silcclient.pc wasn't found, check for just silc.pc
 	if test "x$have_silc" = "xno"; then
-		PKG_CHECK_MODULES(SILC, silc, [
+		PKG_CHECK_MODULES(SILC, silcclient, [
 			have_silc="yes"
-			silcincludes="yes"
-			silcclient="yes"
+			silc10includes="yes"
+			silc10client="yes"
 		], [
 			AC_MSG_RESULT(no)
 			have_silc="no"
 		])
+		dnl If silcclient.pc wasn't found, check for just silc.pc
+		if test "x$have_silc" = "xno"; then
+			PKG_CHECK_MODULES(SILC, silc, [
+				have_silc="yes"
+				silc10includes="yes"
+				silc10client="yes"
+			], [
+				AC_MSG_RESULT(no)
+				have_silc="no"
+			])
+		fi
 	fi
 else
 	if test "$ac_silc_includes" != "no"; then
@@ -677,7 +689,7 @@
 	fi
 	CPPFLAGS_save="$CPPFLAGS"
 	CPPFLAGS="$CPPFLAGS $SILC_CFLAGS"
-	AC_CHECK_HEADER(silcincludes.h, [silcincludes=yes])
+	AC_CHECK_HEADER(silc.h, [silcincludes=yes])
 	CPPFLAGS="$CPPFLAGS_save"
 
 	if test "$ac_silc_libs" != "no"; then
@@ -685,11 +697,28 @@
 	fi
 	SILC_LIBS="$SILC_LIBS -lsilc -lsilcclient -lpthread $LIBDL"
 	AC_CHECK_LIB(silcclient, silc_client_init, [silcclient=yes], , $SILC_LIBS)
+
+	if test "x$silcincludes" = "xyes" -a "x$silcclient" = "xyes"; then
+		have_silc="yes"
+	else
+		CPPFLAGS_save="$CPPFLAGS"
+		CPPFLAGS="$CPPFLAGS $SILC_CFLAGS"
+		AC_CHECK_HEADER(silcincludes.h, [silc10includes=yes])
+		CPPFLAGS="$CPPFLAGS_save"
+
+		SILC_LIBS="$SILC_LIBS -lsilc -lsilcclient -lpthread $LIBDL"
+		AC_CHECK_LIB(silcclient, silc_client_init, [silc10client=yes], , $SILC_LIBS)
+		if test "x$silc10includes" = "xyes" -a "x$silc10client" = "xyes"; then
+			have_silc="yes"
+		fi
+	fi
 fi
 AC_SUBST(SILC_LIBS)
 AC_SUBST(SILC_CFLAGS)
 dnl SILC Toolkit >= 1.0.1 has a new MIME API
 if test "x$silcclient" = "xyes"; then
+	AC_DEFINE(HAVE_SILCMIME_H, 1, [Define if we have silcmime.h])
+elif test "x$silc10client" = "xyes"; then
 	CPPFLAGS_save="$CPPFLAGS"
 	CPPFLAGS="$CPPFLAGS $SILC_CFLAGS"
 		AC_MSG_CHECKING(for silcmime.h)
@@ -794,7 +823,10 @@
 	STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/bonjour//'`
 fi
 if test "x$silcincludes" != "xyes" -o "x$silcclient" != "xyes"; then
-	STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/silc//'`
+	STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/silc/silc10/'`
+fi
+if test "x$silc10includes" != "xyes" -o "x$silc10client" != "xyes"; then
+	STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/silc10//'`
 fi
 AC_SUBST(STATIC_PRPLS)
 STATIC_LINK_LIBS=
@@ -802,13 +834,24 @@
 load_proto=
 for i in $STATIC_PRPLS ; do
 	dnl Ugly special case for "libsilcpurple.a":
-	if test "x$i" = "xsilc"; then
-		STATIC_LINK_LIBS="$STATIC_LINK_LIBS protocols/$i/lib${i}purple.a"
+	dnl ... and Ugly special case for multi-protocol oscar
+	if test \( "x$i" = "xoscar" -o "x$i" = "xaim" -o "x$i" = "xicq" \) -a "x$static_oscar" != "xyes"; then
+		STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/oscar/liboscar.a"
+		extern_init="$extern_init extern gboolean purple_init_aim_plugin();"
+		extern_init="$extern_init extern gboolean purple_init_icq_plugin();"
+		load_proto="$load_proto purple_init_aim_plugin();"
+		load_proto="$load_proto purple_init_icq_plugin();"
 	else
-		STATIC_LINK_LIBS="$STATIC_LINK_LIBS protocols/$i/lib$i.a"
+		if test "x$i" = "xsilc"; then
+			STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib${i}purple.a"
+		elif test "x$i" = "xsilc10"; then
+			STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/libsilcpurple.a"
+		else
+			STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib$i.a"
+		fi
+		extern_init="$extern_init extern gboolean purple_init_${i}_plugin();"
+		load_proto="$load_proto purple_init_${i}_plugin();"
 	fi
-	extern_init="$extern_init extern gboolean purple_init_${i}_plugin();"
-	load_proto="$load_proto purple_init_${i}_plugin();"
 	case $i in
 		bonjour)	static_bonjour=yes ;;
 		gg)			static_gg=yes ;;
@@ -823,6 +866,7 @@
 		qq)			static_qq=yes ;;
 		sametime)	static_sametime=yes ;;
 		silc)		static_silc=yes ;;
+		silc10)		static_silc=yes ;;
 		simple)		static_simple=yes ;;
 		toc)		static_toc=yes ;;
 		yahoo)		static_yahoo=yes ;;
@@ -840,7 +884,7 @@
 AM_CONDITIONAL(STATIC_OSCAR, test "x$static_oscar" = "xyes")
 AM_CONDITIONAL(STATIC_QQ, test "x$static_qq" = "xyes")
 AM_CONDITIONAL(STATIC_SAMETIME, test "x$static_sametime" = "xyes" -a "x$have_meanwhile" = "xyes")
-AM_CONDITIONAL(STATIC_SILC, test "x$static_silc" = "xyes" -a "x$silcincludes" = "xyes" -a "x$silcclient" = "xyes")
+AM_CONDITIONAL(STATIC_SILC, test "x$static_silc" = "xyes" -a "x$have_silc" = "xyes")
 AM_CONDITIONAL(STATIC_SIMPLE, test "x$static_simple" = "xyes")
 AM_CONDITIONAL(STATIC_TOC, test "x$static_toc" = "xyes")
 AM_CONDITIONAL(STATIC_YAHOO, test "x$static_yahoo" = "xyes")
@@ -860,7 +904,10 @@
 	DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/bonjour//'`
 fi
 if test "x$silcincludes" != "xyes" -o "x$silcclient" != "xyes"; then
-	DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/silc//'`
+	DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/silc/silc10/'`
+fi
+if test "x$silc10includes" != "xyes" -o "x$silc10client" != "xyes"; then
+	DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/silc10//'`
 fi
 AC_SUBST(DYNAMIC_PRPLS)
 for i in $DYNAMIC_PRPLS ; do
@@ -878,6 +925,7 @@
 		qq)			dynamic_qq=yes ;;
 		sametime)	dynamic_sametime=yes ;;
 		silc)		dynamic_silc=yes ;;
+		silc10)		dynamic_silc=yes ;;
 		simple)		dynamic_simple=yes ;;
 		toc)		dynamic_toc=yes ;;
 		yahoo)		dynamic_yahoo=yes ;;
@@ -895,7 +943,7 @@
 AM_CONDITIONAL(DYNAMIC_OSCAR, test "x$dynamic_oscar" = "xyes")
 AM_CONDITIONAL(DYNAMIC_QQ, test "x$dynamic_qq" = "xyes")
 AM_CONDITIONAL(DYNAMIC_SAMETIME, test "x$dynamic_sametime" = "xyes" -a "x$have_meanwhile" = "xyes")
-AM_CONDITIONAL(DYNAMIC_SILC, test "x$dynamic_silc" = "xyes" -a "x$silcincludes" = "xyes" -a "x$silcclient" = "xyes")
+AM_CONDITIONAL(DYNAMIC_SILC, test "x$dynamic_silc" = "xyes" -a "x$have_silc" = "xyes")
 AM_CONDITIONAL(DYNAMIC_SIMPLE, test "x$dynamic_simple" = "xyes")
 AM_CONDITIONAL(DYNAMIC_TOC, test "x$dynamic_toc" = "xyes")
 AM_CONDITIONAL(DYNAMIC_YAHOO, test "x$dynamic_yahoo" = "xyes")
@@ -2060,6 +2108,8 @@
 		   pidgin/pixmaps/tray/16/scalable/Makefile
 		   pidgin/pixmaps/tray/22/Makefile
 		   pidgin/pixmaps/tray/22/scalable/Makefile
+		   pidgin/pixmaps/tray/32/Makefile
+		   pidgin/pixmaps/tray/48/Makefile
 		   pidgin/plugins/Makefile
 		   pidgin/plugins/cap/Makefile
 		   pidgin/plugins/gestures/Makefile
@@ -2090,10 +2140,12 @@
 		   libpurple/protocols/msn/Makefile
 		   libpurple/protocols/myspace/Makefile
 		   libpurple/protocols/novell/Makefile
+		   libpurple/protocols/null/Makefile
 		   libpurple/protocols/oscar/Makefile
 		   libpurple/protocols/qq/Makefile
 		   libpurple/protocols/sametime/Makefile
 		   libpurple/protocols/silc/Makefile
+		   libpurple/protocols/silc10/Makefile
 		   libpurple/protocols/simple/Makefile
 		   libpurple/protocols/toc/Makefile
 		   libpurple/protocols/yahoo/Makefile
--- a/doc/funniest_home_convos.txt	Thu Jun 14 19:48:48 2007 +0000
+++ b/doc/funniest_home_convos.txt	Mon Jun 18 01:48:35 2007 +0000
@@ -471,4 +471,6 @@
 14:08 <elb> "... yes"
 14:08 <elb> I mean, what do you say
 14:08 <Robot101> elb: was their nick "idi"?
-          
+
+19:23 <-- elb has quit (K-lined)
+
--- a/finch/gntaccount.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/finch/gntaccount.c	Mon Jun 18 01:48:35 2007 +0000
@@ -717,6 +717,15 @@
 	gnt_tree_remove(GNT_TREE(accounts.tree), account);
 }
 
+static void
+account_abled_cb(PurpleAccount *account, gpointer user_data)
+{
+	if (accounts.window == NULL)
+		return;
+	gnt_tree_set_choice(GNT_TREE(accounts.tree), account,
+			GPOINTER_TO_INT(user_data));
+}
+
 void finch_accounts_init()
 {
 	GList *iter;
@@ -727,7 +736,13 @@
 	purple_signal_connect(purple_accounts_get_handle(), "account-removed",
 			finch_accounts_get_handle(), PURPLE_CALLBACK(account_removed_callback),
 			NULL);
-	
+	purple_signal_connect(purple_accounts_get_handle(), "account-disabled",
+			finch_accounts_get_handle(),
+			PURPLE_CALLBACK(account_abled_cb), GINT_TO_POINTER(FALSE));
+	purple_signal_connect(purple_accounts_get_handle(), "account-enabled",
+			finch_accounts_get_handle(),
+			PURPLE_CALLBACK(account_abled_cb), GINT_TO_POINTER(TRUE));
+
 	for (iter = purple_accounts_get_all(); iter; iter = iter->next) {
 		if (purple_account_get_enabled(iter->data, FINCH_UI))
 			break;
--- a/finch/gntconn.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/finch/gntconn.c	Mon Jun 18 01:48:35 2007 +0000
@@ -24,34 +24,116 @@
  */
 #include "account.h"
 #include "core.h"
+#include "connection.h"
+#include "debug.h"
 #include "request.h"
 
 #include "gntconn.h"
 #include "finch.h"
 
+#define INITIAL_RECON_DELAY_MIN  8000
+#define INITIAL_RECON_DELAY_MAX 60000
+
+#define MAX_RECON_DELAY 600000
+
+typedef struct {
+	int delay;
+	guint timeout;
+} FinchAutoRecon;
+
+/**
+ * Contains accounts that are auto-reconnecting.
+ * The key is a pointer to the PurpleAccount and the
+ * value is a pointer to a FinchAutoRecon.
+ */
+static GHashTable *hash = NULL;
+
+static void
+free_auto_recon(gpointer data)
+{
+	FinchAutoRecon *info = data;
+
+	if (info->timeout != 0)
+		g_source_remove(info->timeout);
+
+	g_free(info);
+}
+
+
+static gboolean
+do_signon(gpointer data)
+{
+	PurpleAccount *account = data;
+	FinchAutoRecon *info;
+	PurpleStatus *status;
+
+	purple_debug_info("autorecon", "do_signon called\n");
+	g_return_val_if_fail(account != NULL, FALSE);
+	info = g_hash_table_lookup(hash, account);
+
+	if (info)
+		info->timeout = 0;
+
+	status = purple_account_get_active_status(account);
+	if (purple_status_is_online(status))
+	{
+		purple_debug_info("autorecon", "calling purple_account_connect\n");
+		purple_account_connect(account);
+		purple_debug_info("autorecon", "done calling purple_account_connect\n");
+	}
+
+	return FALSE;
+}
+
 static void
 finch_connection_report_disconnect(PurpleConnection *gc, const char *text)
 {
-	char *act, *primary, *secondary;
+	FinchAutoRecon *info;
 	PurpleAccount *account = purple_connection_get_account(gc);
 
-	act = g_strdup_printf(_("%s (%s)"), purple_account_get_username(account),
-			purple_account_get_protocol_name(account));
+	info = g_hash_table_lookup(hash, account);
 
-	primary = g_strdup_printf(_("%s disconnected."), act);
-	secondary = g_strdup_printf(_("%s was disconnected due to the following error:\n%s"),
-			act, text);
+	if (!gc->wants_to_die) {
+		if (info == NULL) {
+			info = g_new0(FinchAutoRecon, 1);
+			g_hash_table_insert(hash, account, info);
+			info->delay = g_random_int_range(INITIAL_RECON_DELAY_MIN, INITIAL_RECON_DELAY_MAX);
+		} else {
+			info->delay = MIN(2 * info->delay, MAX_RECON_DELAY);
+			if (info->timeout != 0)
+				g_source_remove(info->timeout);
+		}
+		info->timeout = g_timeout_add(info->delay, do_signon, account);
+	} else {
+		char *act, *primary, *secondary;
+		act = g_strdup_printf(_("%s (%s)"), purple_account_get_username(account),
+				purple_account_get_protocol_name(account));
 
-	purple_request_action(account, _("Connection Error"), primary, secondary, 1,
-						account, NULL, NULL,
-						account, 2,
-						_("OK"), NULL,
-						_("Connect"),
-						PURPLE_CALLBACK(purple_account_connect));
+		primary = g_strdup_printf(_("%s disconnected."), act);
+		secondary = g_strdup_printf(_("%s\n\n"
+				"Finch will not attempt to reconnect the account until you "
+				"correct the error and re-enable the account."), text);
+		purple_notify_error(NULL, NULL, primary, secondary);
+
+		g_free(act);
+		g_free(primary);
+		g_free(secondary);
+		purple_account_set_enabled(account, FINCH_UI, FALSE);
+	}
+}
 
-	g_free(act);
-	g_free(primary);
-	g_free(secondary);
+static void
+account_removed_cb(PurpleAccount *account, gpointer user_data)
+{
+	g_hash_table_remove(hash, account);
+}
+
+static void *
+finch_connection_get_handle(void)
+{
+	static int handle;
+
+	return &handle;
 }
 
 static PurpleConnectionUiOps ops = 
@@ -75,8 +157,18 @@
 }
 
 void finch_connections_init()
-{}
+{
+	hash = g_hash_table_new_full(
+							g_direct_hash, g_direct_equal,
+							NULL, free_auto_recon);
+
+	purple_signal_connect(purple_accounts_get_handle(), "account-removed",
+						finch_connection_get_handle(),
+						PURPLE_CALLBACK(account_removed_cb), NULL);
+}
 
 void finch_connections_uninit()
-{}
-
+{
+	purple_signals_disconnect_by_handle(finch_connection_get_handle());
+	g_hash_table_destroy(hash);
+}
--- a/finch/gntrequest.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/finch/gntrequest.c	Mon Jun 18 01:48:35 2007 +0000
@@ -672,10 +672,13 @@
 			pt = purple_prefs_get_type(id);
 			switch (pt) {
 				case PURPLE_PREF_INT:
+				{
+					long int tmp;
 					if (type == PURPLE_REQUEST_FIELD_LIST) /* Lists always return string */
-						sscanf(val, "%ld", (long int *)&val);
-					purple_prefs_set_int(id, GPOINTER_TO_INT(val));
+						sscanf(val, "%ld", &tmp);
+					purple_prefs_set_int(id, (gint)tmp);
 					break;
+				}
 				case PURPLE_PREF_BOOLEAN:
 					purple_prefs_set_bool(id, GPOINTER_TO_INT(val));
 					break;
--- a/libpurple/Makefile.mingw	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/Makefile.mingw	Mon Jun 18 01:48:35 2007 +0000
@@ -72,6 +72,7 @@
 			upnp.c \
 			util.c \
 			value.c \
+			version.c \
 			xmlnode.c \
 			whiteboard.c \
 			win32/giowin32.c \
@@ -120,7 +121,7 @@
 $(OBJECTS): $(PURPLE_CONFIG_H) $(PURPLE_VERSION_H)
 
 $(TARGET).dll $(TARGET).dll.a: $(OBJECTS)
-	$(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--out-implib,$(TARGET).dll.a -o $(TARGET).dll
+	$(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--output-def,$(TARGET).def,--out-implib,$(TARGET).dll.a -o $(TARGET).dll
 
 ##
 ## CLEAN RULES
--- a/libpurple/blist.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/blist.c	Mon Jun 18 01:48:35 2007 +0000
@@ -1774,7 +1774,7 @@
 
 	node = (PurpleBlistNode *)buddy;
 	cnode = node->parent;
-	gnode = cnode->parent;
+	gnode = (cnode != NULL) ? cnode->parent : NULL;
 	contact = (PurpleContact *)cnode;
 	group = (PurpleGroup *)gnode;
 
@@ -1783,35 +1783,37 @@
 		node->prev->next = node->next;
 	if (node->next)
 		node->next->prev = node->prev;
-	if (cnode->child == node)
+	if ((cnode != NULL) && (cnode->child == node))
 		cnode->child = node->next;
 
 	/* Adjust size counts */
-	if (PURPLE_BUDDY_IS_ONLINE(buddy)) {
-		contact->online--;
-		if (contact->online == 0)
-			group->online--;
+	if (contact != NULL) {
+		if (PURPLE_BUDDY_IS_ONLINE(buddy)) {
+			contact->online--;
+			if (contact->online == 0)
+				group->online--;
+		}
+		if (purple_account_is_connected(buddy->account)) {
+			contact->currentsize--;
+			if (contact->currentsize == 0)
+				group->currentsize--;
+		}
+		contact->totalsize--;
+
+		/* Re-sort the contact */
+		if (cnode->child && contact->priority == buddy) {
+			purple_contact_invalidate_priority_buddy(contact);
+			if (ops && ops->update)
+				ops->update(purplebuddylist, cnode);
+		}
 	}
-	if (purple_account_is_connected(buddy->account)) {
-		contact->currentsize--;
-		if (contact->currentsize == 0)
-			group->currentsize--;
-	}
-	contact->totalsize--;
 
 	purple_blist_schedule_save();
 
-	/* Re-sort the contact */
-	if (cnode->child && contact->priority == buddy) {
-		purple_contact_invalidate_priority_buddy(contact);
-		if (ops && ops->update)
-			ops->update(purplebuddylist, cnode);
-	}
-
 	/* Remove this buddy from the buddies hash table */
 	hb.name = g_strdup(purple_normalize(buddy->account, buddy->name));
 	hb.account = buddy->account;
-	hb.group = ((PurpleBlistNode*)buddy)->parent->parent;
+	hb.group = gnode;
 	g_hash_table_remove(purplebuddylist->buddies, &hb);
 	g_free(hb.name);
 
@@ -1841,7 +1843,7 @@
 	while (g_source_remove_by_user_data((gpointer *)buddy));
 
 	/* If the contact is empty then remove it */
-	if (!cnode->child)
+	if ((contact != NULL) && !cnode->child)
 		purple_blist_remove_contact(contact);
 }
 
--- a/libpurple/cipher.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/cipher.c	Mon Jun 18 01:48:35 2007 +0000
@@ -1447,14 +1447,14 @@
  * Structs
  ******************************************************************************/
 struct _PurpleCipher {
-	gchar *name;
-	PurpleCipherOps *ops;
-	guint ref;
+	gchar *name;          /**< Internal name - used for searching */
+	PurpleCipherOps *ops; /**< Operations supported by this cipher */
+	guint ref;            /**< Reference count */
 };
 
 struct _PurpleCipherContext {
-	PurpleCipher *cipher;
-	gpointer data;
+	PurpleCipher *cipher; /**< Cipher this context is under */
+	gpointer data;        /**< Internal cipher state data */
 };
 
 /******************************************************************************
--- a/libpurple/connection.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/connection.c	Mon Jun 18 01:48:35 2007 +0000
@@ -436,7 +436,7 @@
 	g_return_if_fail(gc   != NULL);
 
 	if (text == NULL) {
-		g_critical("purple_connection_error: check `text != NULL' failed");
+		purple_debug_error("connection", "purple_connection_error: check `text != NULL' failed");
 		text = _("Unknown error");
 	}
 
--- a/libpurple/connection.h	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/connection.h	Mon Jun 18 01:48:35 2007 +0000
@@ -279,7 +279,7 @@
  * TODO: Eventually this bad boy will be removed, because it is
  *       a gross fix for a crashy problem.
  */
-#define PURPLE_CONNECTION_IS_VALID(gc) (g_list_find(purple_connections_get_all(), (gc)))
+#define PURPLE_CONNECTION_IS_VALID(gc) (g_list_find(purple_connections_get_all(), (gc)) != NULL)
 
 /*@}*/
 
--- a/libpurple/conversation.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/conversation.c	Mon Jun 18 01:48:35 2007 +0000
@@ -1535,20 +1535,22 @@
 		PurpleConvChatBuddyFlags flag = GPOINTER_TO_INT(fl->data);
 		const char *extra_msg = (extra_msgs ? extra_msgs->data : NULL);
 
-		if (!strcmp(chat->nick, purple_normalize(conv->account, user))) {
-			const char *alias2 = purple_account_get_alias(conv->account);
-			if (alias2 != NULL)
-				alias = alias2;
-			else
-			{
-				const char *display_name = purple_connection_get_display_name(gc);
-				if (display_name != NULL)
-					alias = display_name;
+		if(!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
+			if (!strcmp(chat->nick, purple_normalize(conv->account, user))) {
+				const char *alias2 = purple_account_get_alias(conv->account);
+				if (alias2 != NULL)
+					alias = alias2;
+				else
+				{
+					const char *display_name = purple_connection_get_display_name(gc);
+					if (display_name != NULL)
+						alias = display_name;
+				}
+			} else {
+				PurpleBuddy *buddy;
+				if ((buddy = purple_find_buddy(gc->account, user)) != NULL)
+					alias = purple_buddy_get_contact_alias(buddy);
 			}
-		} else if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
-			PurpleBuddy *buddy;
-			if ((buddy = purple_find_buddy(gc->account, user)) != NULL)
-				alias = purple_buddy_get_contact_alias(buddy);
 		}
 
 		quiet = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_conversations_get_handle(),
@@ -1633,14 +1635,16 @@
 		/* Note this for later. */
 		is_me = TRUE;
 
-		alias = purple_account_get_alias(conv->account);
-		if (alias != NULL)
-			new_alias = alias;
-		else
-		{
-			const char *display_name = purple_connection_get_display_name(gc);
-			if (display_name != NULL)
-				alias = display_name;
+		if(!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
+			alias = purple_account_get_alias(conv->account);
+			if (alias != NULL)
+				new_alias = alias;
+			else
+			{
+				const char *display_name = purple_connection_get_display_name(gc);
+				if (display_name != NULL)
+					alias = display_name;
+			}
 		}
 	} else if (!(prpl_info->options & OPT_PROTO_UNIQUE_CHATNAME)) {
 		PurpleBuddy *buddy;
@@ -1806,7 +1810,7 @@
 	if (ops != NULL && ops->chat_remove_users != NULL) {
 		for (l = users; l; l = l->next) {
 			PurpleConvChatBuddy *cb = l->data;
-			names = g_list_append(names, cb->name);
+			names = g_list_prepend(names, cb->name);
 		}
 		ops->chat_remove_users(conv, names);
 		g_list_free(names);
@@ -1960,7 +1964,7 @@
 
 	for (l = purple_conv_chat_get_users(chat); l; l = l->next) {
 		cb = l->data;
-		if (!purple_utf8_strcasecmp(cb->name, name))
+		if (!g_utf8_collate(cb->name, name))
 			return cb;
 	}
 
--- a/libpurple/dbus-analyze-functions.py	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/dbus-analyze-functions.py	Mon Jun 18 01:48:35 2007 +0000
@@ -2,7 +2,6 @@
 import string
 import sys
 
-
 # types translated into "int"
 simpletypes = ["int", "gint", "guint", "gboolean"]
 
@@ -166,8 +165,11 @@
         self.returncode = []
 
     def flush(self):
+        paramslist = ", ".join(self.paramshdr)
+        if (paramslist == "") :
+            paramslist = "void"
         print "%s %s(%s)" % (self.functiontype, self.function.name,
-                             ", ".join(self.paramshdr)),
+                             paramslist),
 
         if self.headersonly:
             print ";"
@@ -277,7 +279,7 @@
         for decl in self.cdecls:
             print decl
 
-        print "\t%s(message_DBUS, error_DBUS, " % self.argfunc,
+        print "\t%s(message_DBUS, error_DBUS," % self.argfunc,
         for param in self.cparams:
             print "DBUS_TYPE_%s, &%s," % param,
         print "DBUS_TYPE_INVALID);"
@@ -287,14 +289,14 @@
         for code in self.ccode:
             print code
 
-        print "\treply_DBUS =  dbus_message_new_method_return (message_DBUS);"
+        print "\treply_DBUS = dbus_message_new_method_return (message_DBUS);"
 
-        print "\tdbus_message_append_args(reply_DBUS, ",
+        print "\tdbus_message_append_args(reply_DBUS,",
         for param in self.cparamsout:
             if type(param) is str:
-                print "%s, " % param
+                print "%s," % param
             else:
-                print "DBUS_TYPE_%s, &%s, " % param,
+                print "DBUS_TYPE_%s, &%s," % param,
         print "DBUS_TYPE_INVALID);"
 
         for code in self.ccodeout:
@@ -359,8 +361,12 @@
         self.ccode.append("\t%s;" % self.call) # just call the function
 
     def outputstring(self, type, name, const):
-        self.cdecls.append("\tconst char *%s;" % name)
-        self.ccode.append("\t%s = null_to_empty(%s);" % (name, self.call))
+        if const:
+            self.cdecls.append("\tconst char *%s;" % name)
+        else:
+            self.cdecls.append("\tchar *%s;" % name)
+        self.ccode.append("\tif ((%s = %s) == NULL)" % (name, self.call))
+        self.ccode.append("\t\t%s = \"\";" % (name))
         self.cparamsout.append(("STRING", name))
         self.addouttype("s", name)
         if not const:
--- a/libpurple/dbus-bindings.h	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/dbus-bindings.h	Mon Jun 18 01:48:35 2007 +0000
@@ -35,9 +35,9 @@
 extern "C" {
 #endif
 
-gint purple_dbus_pointer_to_id(gpointer node);
+gint purple_dbus_pointer_to_id(gconstpointer node);
 gpointer purple_dbus_id_to_pointer(gint id, PurpleDBusType *type);
-gint  purple_dbus_pointer_to_id_error(gpointer ptr, DBusError *error);
+gint  purple_dbus_pointer_to_id_error(gconstpointer ptr, DBusError *error);
 gpointer purple_dbus_id_to_pointer_error(gint id, PurpleDBusType *type,
 				       const char *typename, DBusError *error);
 
--- a/libpurple/dbus-server.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/dbus-server.c	Mon Jun 18 01:48:35 2007 +0000
@@ -108,14 +108,14 @@
 }
 
 gint
-purple_dbus_pointer_to_id(gpointer node)
+purple_dbus_pointer_to_id(gconstpointer node)
 {
 	gint id = GPOINTER_TO_INT(g_hash_table_lookup(map_node_id, node));
 	if ((id == 0) && (node != NULL))
 	{
 		purple_debug_warning("dbus",
 				"Need to register an object with the dbus subsystem.\n");
-		g_return_val_if_reached(0);
+		return 0;
 	}
 	return id;
 }
@@ -138,7 +138,7 @@
 }
 
 gint
-purple_dbus_pointer_to_id_error(gpointer ptr, DBusError *error)
+purple_dbus_pointer_to_id_error(gconstpointer ptr, DBusError *error)
 {
 	gint id = purple_dbus_pointer_to_id(ptr);
 
--- a/libpurple/idle.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/idle.c	Mon Jun 18 01:48:35 2007 +0000
@@ -92,7 +92,7 @@
 }
 
 
-static int no_away = 0;
+static gboolean no_away = FALSE;
 static gint time_until_next_idle_event;
 /*
  * This function should be called when you think your idle state
@@ -118,15 +118,15 @@
 	time_t time_idle;
 	gboolean auto_away;
 	const gchar *idle_reporting;
-	gboolean report_idle;
-	GList *l;
+	gboolean report_idle = TRUE;
 	gint away_seconds = 0;
-	gint idle_recheck_interval;
+	gint idle_recheck_interval = 0;
 
 	purple_signal_emit(purple_blist_get_handle(), "update-idle");
 
 	idle_reporting = purple_prefs_get_string("/purple/away/idle_reporting");
-	report_idle = TRUE;
+	auto_away = purple_prefs_get_bool("/purple/away/away_when_idle");
+
 	if (!strcmp(idle_reporting, "system") &&
 		(idle_ui_ops != NULL) && (idle_ui_ops->get_time_idle != NULL))
 	{
@@ -145,15 +145,9 @@
 		/* Don't report idle time */
 		time_idle = 0;
 		report_idle = FALSE;
-	}
 
-	/* Auto-away stuff */
-	auto_away = purple_prefs_get_bool("/purple/away/away_when_idle");
-
-	/* If we're not reporting idle, we can still do auto-away.
-	 * First try "system" and if that isn't possible, use "purple" */
-	if (!report_idle)
-	{
+		/* If we're not reporting idle, we can still do auto-away.
+		 * First try "system" and if that isn't possible, use "purple" */
 		if (auto_away)
 		{
 			if ((idle_ui_ops != NULL) && (idle_ui_ops->get_time_idle != NULL))
@@ -172,7 +166,7 @@
 			if (!no_away)
 			{
 				purple_savedstatus_set_idleaway(FALSE);
-				no_away = 1;
+				no_away = TRUE;
 			}
 			time_until_next_idle_event = 0;
 			return;
@@ -192,11 +186,11 @@
 	if (auto_away && time_idle > away_seconds)
 	{
 		purple_savedstatus_set_idleaway(TRUE);
-		no_away = 0;
+		no_away = FALSE;
 	}
 	else if (!no_away && time_idle < away_seconds)
 	{
-		no_away = 1;
+		no_away = TRUE;
 		purple_savedstatus_set_idleaway(FALSE);
 		if (time_until_next_idle_event == 0 || (away_seconds - time_idle) < time_until_next_idle_event)
 			time_until_next_idle_event = away_seconds - time_idle;
@@ -205,6 +199,7 @@
 	/* Idle reporting stuff */
 	if (report_idle && (time_idle >= IDLEMARK))
 	{
+		GList *l;
 		for (l = purple_connections_get_all(); l != NULL; l = l->next)
 		{
 			PurpleConnection *gc = l->data;
@@ -305,6 +300,14 @@
 	return &handle;
 }
 
+static gboolean _do_purple_idle_touch_cb(gpointer data)
+{
+	purple_idle_touch();
+
+	return FALSE;
+}
+
+
 void
 purple_idle_init()
 {
@@ -324,7 +327,10 @@
 	purple_prefs_connect_callback(purple_idle_get_handle(), "/purple/away/idle_reporting",
 	                              idle_reporting_cb, NULL);
 
-	purple_idle_touch();
+	/* Initialize the idleness asynchronously so it doesn't check idleness,
+	 * and potentially try to change the status before the UI is initialized */
+	g_idle_add(_do_purple_idle_touch_cb, NULL);
+
 }
 
 void
--- a/libpurple/network.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/network.c	Mon Jun 18 01:48:35 2007 +0000
@@ -598,8 +598,6 @@
 void
 nm_callback_func(libnm_glib_ctx* ctx, gpointer user_data)
 {
-	GList *l;
-	PurpleAccount *account;
 	static libnm_glib_state prev = LIBNM_NO_DBUS;
 	libnm_glib_state current;
 	PurpleConnectionUiOps *ui_ops = purple_connections_get_ui_ops();
--- a/libpurple/notify.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/notify.c	Mon Jun 18 01:48:35 2007 +0000
@@ -749,18 +749,16 @@
 void
 purple_notify_close_with_handle(void *handle)
 {
-	GList *l, *l_next;
+	GList *l, *prev = NULL;
 	PurpleNotifyUiOps *ops;
 
 	g_return_if_fail(handle != NULL);
 
 	ops = purple_notify_get_ui_ops();
 
-	for (l = handles; l != NULL; l = l_next) {
+	for (l = handles; l != NULL; l = prev ? prev->next : handles) {
 		PurpleNotifyInfo *info = l->data;
 
-		l_next = l->next;
-
 		if (info->handle == handle) {
 			handles = g_list_remove(handles, info);
 
@@ -771,7 +769,8 @@
 				info->cb(info->cb_user_data);
 
 			g_free(info);
-		}
+		} else
+			prev = l;
 	}
 }
 
--- a/libpurple/plugins/Makefile.mingw	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/plugins/Makefile.mingw	Mon Jun 18 01:48:35 2007 +0000
@@ -63,6 +63,7 @@
 		autoaccept.dll \
 		buddynote.dll \
 		idle.dll \
+		joinpart.dll \
 		log_reader.dll \
 		newline.dll \
 		offlinemsg.dll \
--- a/libpurple/plugins/buddynote.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/plugins/buddynote.c	Mon Jun 18 01:48:35 2007 +0000
@@ -58,6 +58,9 @@
 {
 	PurpleMenuAction *bna = NULL;
 
+	if (purple_blist_node_get_flags(node) & PURPLE_BLIST_NODE_FLAG_NO_SAVE)
+		return;
+
 	*m = g_list_append(*m, bna);
 	bna = purple_menu_action_new(_("Edit Notes..."), PURPLE_CALLBACK(buddynote_edit_cb), NULL, NULL);
 	*m = g_list_append(*m, bna);
--- a/libpurple/plugins/joinpart.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/plugins/joinpart.c	Mon Jun 18 01:48:35 2007 +0000
@@ -210,7 +210,7 @@
 	 * we don't have to worry one will be called after this. */
 	g_hash_table_destroy((GHashTable *)data[0]);
 
-	g_source_remove(GPOINTER_TO_UINT(data[1]));
+	purple_timeout_remove(GPOINTER_TO_UINT(data[1]));
 	g_free(data);
 
 	return TRUE;
--- a/libpurple/plugins/log_reader.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/plugins/log_reader.c	Mon Jun 18 01:48:35 2007 +0000
@@ -1425,7 +1425,7 @@
 	char *escaped;
 	GString *formatted;
 	char *c;
-	char *line;
+	const char *line;
 
 	g_return_val_if_fail(log != NULL, g_strdup(""));
 
@@ -1460,221 +1460,234 @@
 	read = escaped;
 
 	/* Apply formatting... */
-	formatted = g_string_new("");
+	formatted = g_string_sized_new(strlen(read));
 	c = read;
 	line = read;
-	while (*c)
+	while (c)
 	{
-		if (*c == '\n')
-		{
-			char *link_temp_line;
-			char *link;
-			char *timestamp;
-			char *footer = NULL;
-			*c = '\0';
+		const char *link;
+		const char *footer = NULL;
+		GString *temp = NULL;
 
-			/* Convert links.
-			 *
-			 * The format is (Link: URL)URL
-			 * So, I want to find each occurance of "(Link: " and replace that chunk with:
-			 * <a href="
-			 * Then, replace the next ")" with:
-			 * ">
-			 * Then, replace the next " " (or add this if the end-of-line is reached) with:
-			 * </a>
-			 */
-			link_temp_line = NULL;
-			while ((link = g_strstr_len(line, strlen(line), "(Link: "))) {
-				GString *temp;
-
-				if (!*link)
-					continue;
-
-				*link = '\0';
-				link++;
-
-				temp = g_string_new(line);
-				g_string_append(temp, "<a href=\"");
-
-				if (strlen(link) >= 6) {
-					link += (sizeof("(Link: ") - 1);
+		if ((c = strstr(c, "\n")))
+		{
+			*c = '\0';
+			c++;
+		}
 
-					while (*link && *link != ')') {
-						g_string_append_c(temp, *link);
-						link++;
-					}
-					if (link) {
-						link++;
-
-						g_string_append(temp, "\">");
-						while (*link && *link != ' ') {
-							g_string_append_c(temp, *link);
-							link++;
-						}
-						g_string_append(temp, "</a>");
-					}
-
-					g_string_append(temp, link);
-
-					/* Free the last round's line. */
-					if (link_temp_line)
-						g_free(line);
+		/* Convert links.
+		 *
+		 * The format is (Link: URL)URL
+		 * So, I want to find each occurance of "(Link: " and replace that chunk with:
+		 * <a href="
+		 * Then, replace the next ")" with:
+		 * ">
+		 * Then, replace the next " " (or add this if the end-of-line is reached) with:
+		 * </a>
+		 * 
+		 * As implemented, this isn't perfect, but it should cover common cases.
+		 */
+		while (line && (link = strstr(line, "(Link: ")))
+		{
+			const char *tmp = link;
 
-					line = temp->str;
-					g_string_free(temp, FALSE);
-
-					/* Save this memory location so we can free it later. */
-					link_temp_line = line;
-				}
-			}
+			link += 7;
+			if (*link)
+			{
+				char *end_paren;
+				char *space;
 
-			timestamp = "";
-			if (*line == '[') {
-				timestamp = line;
-				while (*timestamp && *timestamp != ']')
-					timestamp++;
-				if (*timestamp == ']') {
-					*timestamp = '\0';
-					line++;
-					/* TODO: Parse the timestamp and convert it to Purple's format. */
-					g_string_append_printf(formatted,
-						"<font size=\"2\">(%s)</font> ", line);
-					line = timestamp;
-					if (line[1] && line[2])
-						line += 2;
+				if (!(end_paren = strstr(link, ")")))
+				{
+					/* Something is not as we expect.  Bail out. */
+					break;
 				}
 
-				if (purple_str_has_prefix(line, "*** ")) {
-					line += (sizeof("*** ") - 1);
-					g_string_append(formatted, "<b>");
-					footer = "</b>";
-					if (purple_str_has_prefix(line, "NOTE: This user is offline.")) {
-						line = _("User is offline.");
-					} else if (purple_str_has_prefix(line,
-							"NOTE: Your status is currently set to ")) {
+				if (!temp)
+					temp = g_string_sized_new(c ? (c - 1 - line) : strlen(line));
+
+				g_string_append_len(temp, line, (tmp - line));
+
+				/* Start an <a> tag. */
+				g_string_append(temp, "<a href=\"");
+
+				/* Append up to the ) */
+				g_string_append_len(temp, link, end_paren - link);
+
+				/* Finish the <a> tag. */
+				g_string_append(temp, "\">");
+
+				/* The \r is a bit of a hack to keep there from being a \r in
+				 * the link text, which may not matter. */
+				if ((space = strstr(end_paren, " ")) || (space = strstr(end_paren, "\r")))
+				{
+					g_string_append_len(temp, end_paren + 1, space - end_paren - 1);
+
+					/* Close the <a> tag. */
+					g_string_append(temp, "</a>");
+
+					space++;
+				}
+				else
+				{
+					/* There is no space before the end of the line. */
+					g_string_append(temp, end_paren + 1);
+					/* Close the <a> tag. */
+					g_string_append(temp, "</a>");
+				}
+				line = space;
+			}
+			else
+			{
+				/* Something is not as we expect.  Bail out. */
+				break;
+			}
+		}
+
+		if (temp)
+		{
+			if (line)
+				g_string_append(temp, line);
+			line = temp->str;
+		}
+
+		if (*line == '[') {
+			const char *timestamp;
+
+			if ((timestamp = strstr(line, "]"))) {
+				line++;
+				/* TODO: Parse the timestamp and convert it to Purple's format. */
+				g_string_append(formatted, "<font size=\"2\">(");
+				g_string_append_len(formatted, line, (timestamp - line));
+				g_string_append(formatted,")</font> ");
+				line = timestamp + 1;
+				if (line[0] && line[1])
+					line++;
+			}
 
-						line += (sizeof("NOTE: ") - 1);
-					} else if (purple_str_has_prefix(line, "Auto-response sent to ")) {
-						g_string_append(formatted, _("Auto-response sent:"));
-						while (*line && *line != ':')
-							line++;
-						if (*line)
-							line++;
-						g_string_append(formatted, "</b>");
-						footer = NULL;
-					} else if (strstr(line, " signed off ")) {
-						if (buddy != NULL && buddy->alias)
-							g_string_append_printf(formatted,
-								_("%s has signed off."), buddy->alias);
-						else
-							g_string_append_printf(formatted,
-								_("%s has signed off."), log->name);
-						line = "";
-					} else if (strstr(line, " signed on ")) {
-						if (buddy != NULL && buddy->alias)
-							g_string_append(formatted, buddy->alias);
-						else
-							g_string_append(formatted, log->name);
-						line = " logged in.";
-					} else if (purple_str_has_prefix(line,
-						"One or more messages may have been undeliverable.")) {
+			if (purple_str_has_prefix(line, "*** ")) {
+				line += (sizeof("*** ") - 1);
+				g_string_append(formatted, "<b>");
+				footer = "</b>";
+				if (purple_str_has_prefix(line, "NOTE: This user is offline.")) {
+					line = _("User is offline.");
+				} else if (purple_str_has_prefix(line,
+						"NOTE: Your status is currently set to ")) {
+
+					line += (sizeof("NOTE: ") - 1);
+				} else if (purple_str_has_prefix(line, "Auto-response sent to ")) {
+					g_string_append(formatted, _("Auto-response sent:"));
+					while (*line && *line != ':')
+						line++;
+					if (*line)
+						line++;
+					g_string_append(formatted, "</b>");
+					footer = NULL;
+				} else if (strstr(line, " signed off ")) {
+					if (buddy != NULL && buddy->alias)
+						g_string_append_printf(formatted,
+							_("%s has signed off."), buddy->alias);
+					else
+						g_string_append_printf(formatted,
+							_("%s has signed off."), log->name);
+					line = "";
+				} else if (strstr(line, " signed on ")) {
+					if (buddy != NULL && buddy->alias)
+						g_string_append(formatted, buddy->alias);
+					else
+						g_string_append(formatted, log->name);
+					line = " logged in.";
+				} else if (purple_str_has_prefix(line,
+					"One or more messages may have been undeliverable.")) {
 
-						g_string_append(formatted,
-							"<span style=\"color: #ff0000;\">");
-						g_string_append(formatted,
-							_("One or more messages may have been "
-							  "undeliverable."));
-						line = "";
-						footer = "</span></b>";
-					} else if (purple_str_has_prefix(line,
-							"You have been disconnected.")) {
+					g_string_append(formatted,
+						"<span style=\"color: #ff0000;\">");
+					g_string_append(formatted,
+						_("One or more messages may have been "
+						  "undeliverable."));
+					line = "";
+					footer = "</span></b>";
+				} else if (purple_str_has_prefix(line,
+						"You have been disconnected.")) {
 
-						g_string_append(formatted,
-							"<span style=\"color: #ff0000;\">");
-						g_string_append(formatted,
-							_("You were disconnected from the server."));
-						line = "";
-						footer = "</span></b>";
-					} else if (purple_str_has_prefix(line,
-							"You are currently disconnected.")) {
+					g_string_append(formatted,
+						"<span style=\"color: #ff0000;\">");
+					g_string_append(formatted,
+						_("You were disconnected from the server."));
+					line = "";
+					footer = "</span></b>";
+				} else if (purple_str_has_prefix(line,
+						"You are currently disconnected.")) {
+
+					g_string_append(formatted,
+						"<span style=\"color: #ff0000;\">");
+					line = _("You are currently disconnected. Messages "
+					         "will not be received unless you are "
+					         "logged in.");
+					footer = "</span></b>";
+				} else if (purple_str_has_prefix(line,
+						"Your previous message has not been sent.")) {
+
+					g_string_append(formatted,
+						"<span style=\"color: #ff0000;\">");
+
+					if (purple_str_has_prefix(line,
+						"Your previous message has not been sent.  "
+						"Reason: Maximum length exceeded.")) {
 
 						g_string_append(formatted,
-							"<span style=\"color: #ff0000;\">");
-						line = _("You are currently disconnected. Messages "
-						         "will not be received unless you are "
-						         "logged in.");
-						footer = "</span></b>";
-					} else if (purple_str_has_prefix(line,
-							"Your previous message has not been sent.")) {
-
+							_("Message could not be sent because "
+							  "the maximum length was exceeded."));
+						line = "";
+					} else {
 						g_string_append(formatted,
-							"<span style=\"color: #ff0000;\">");
-
-						if (purple_str_has_prefix(line,
-							"Your previous message has not been sent.  "
-							"Reason: Maximum length exceeded.")) {
+							_("Message could not be sent."));
+						line += (sizeof(
+							"Your previous message "
+							"has not been sent. ") - 1);
+					}
 
-							g_string_append(formatted,
-								_("Message could not be sent because "
-								  "the maximum length was exceeded."));
-							line = "";
-						} else {
-							g_string_append(formatted,
-								_("Message could not be sent."));
-							line += (sizeof(
-								"Your previous message "
-								"has not been sent. ") - 1);
-						}
+					footer = "</span></b>";
+				}
+			} else if (purple_str_has_prefix(line, data->their_nickname)) {
+				if (buddy != NULL && buddy->alias) {
+					line += strlen(data->their_nickname) + 2;
+					g_string_append_printf(formatted,
+						"<span style=\"color: #A82F2F;\">"
+						"<b>%s</b></span>: ", buddy->alias);
+				}
+			} else {
+				const char *line2 = strstr(line, ":");
+				if (line2) {
+					const char *acct_name;
+					line2++;
+					line = line2;
+					acct_name = purple_account_get_alias(log->account);
+					if (!acct_name)
+						acct_name = purple_account_get_username(log->account);
 
-						footer = "</span></b>";
-					}
-				} else if (purple_str_has_prefix(line, data->their_nickname)) {
-					if (buddy != NULL && buddy->alias) {
-						line += strlen(data->their_nickname) + 2;
-						g_string_append_printf(formatted,
-							"<span style=\"color: #A82F2F;\">"
-							"<b>%s</b></span>: ", buddy->alias);
-					}
-				} else {
-					char *line2 = line;
-					while (*line2 && *line2 != ':')
-						line2++;
-					if (*line2 == ':') {
-						const char *acct_name;
-						line2++;
-						line = line2;
-						acct_name = purple_account_get_alias(log->account);
-						if (!acct_name)
-							acct_name = purple_account_get_username(log->account);
-
-						g_string_append_printf(formatted,
-							"<span style=\"color: #16569E;\">"
-							"<b>%s</b></span>:", acct_name);
-					}
+					g_string_append_printf(formatted,
+						"<span style=\"color: #16569E;\">"
+						"<b>%s</b></span>:", acct_name);
 				}
 			}
-
-			g_string_append(formatted, line);
+		}
 
-			if (footer)
-				g_string_append(formatted, footer);
-
-			g_string_append_c(formatted, '\n');
+		g_string_append(formatted, line);
 
-			if (link_temp_line)
-				g_free(link_temp_line);
+		line = c;
+		if (temp)
+			g_string_free(temp, TRUE);
 
-			c++;
-			line = c;
-		} else
-			c++;
+		if (footer)
+			g_string_append(formatted, footer);
+
+		g_string_append_c(formatted, '\n');
 	}
 
 	g_free(read);
-	read = formatted->str;
-	g_string_free(formatted, FALSE);
-
-	return read;
+	/* XXX: TODO: Avoid this g_strchomp() */
+	return g_strchomp(g_string_free(formatted, FALSE));
 }
 
 static int trillian_logger_size (PurpleLog *log)
--- a/libpurple/plugins/newline.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/plugins/newline.c	Mon Jun 18 01:48:35 2007 +0000
@@ -32,7 +32,7 @@
 					 PurpleConversation *conv, int *flags, void *data)
 {
 	if (g_ascii_strncasecmp(*message, "/me ", strlen("/me "))) {
-		char *tmp = g_strdup_printf("\n%s", *message);
+		char *tmp = g_strdup_printf("<br/>%s", *message);
 		g_free(*message);
 		*message = tmp;
 	}
--- a/libpurple/plugins/perl/perl-common.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/plugins/perl/perl-common.c	Mon Jun 18 01:48:35 2007 +0000
@@ -205,7 +205,7 @@
 		purple_debug(PURPLE_DEBUG_ERROR, "perl",
 				   "Perl function %s exited abnormally: %s\n",
 				   function, SvPV(ERRSV, na));
-		POPs;
+		(void)POPs;
 	} else if (count != 1) {
 		/*
 		 * This should NEVER happen.  G_SCALAR ensures that we WILL
--- a/libpurple/plugins/perl/perl-handlers.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/plugins/perl/perl-handlers.c	Mon Jun 18 01:48:35 2007 +0000
@@ -184,7 +184,7 @@
 	timeout_handlers = g_list_remove(timeout_handlers, handler);
 
 	if (handler->iotag > 0)
-		g_source_remove(handler->iotag);
+		purple_timeout_remove(handler->iotag);
 
 	if (handler->callback != NULL)
 		SvREFCNT_dec(handler->callback);
@@ -405,7 +405,7 @@
 
 	timeout_handlers = g_list_append(timeout_handlers, handler);
 
-	handler->iotag = g_timeout_add(seconds * 1000, perl_timeout_cb, handler);
+	handler->iotag = purple_timeout_add(seconds * 1000, perl_timeout_cb, handler);
 }
 
 void
--- a/libpurple/plugins/ssl/ssl-gnutls.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/plugins/ssl/ssl-gnutls.c	Mon Jun 18 01:48:35 2007 +0000
@@ -123,6 +123,18 @@
 	gnutls_data->handshake_handler = purple_input_add(gsc->fd,
 		PURPLE_INPUT_READ, ssl_gnutls_handshake_cb, gsc);
 
+	/* Orborde asks: Why are we configuring a callback, then
+	   immediately calling it?
+
+	   Answer: gnutls_handshake (up in handshake_cb) needs to be called
+	   once in order to get the ball rolling on the SSL connection.
+	   Once it has done so, only then will the server reply, triggering
+	   the callback.
+
+	   Since the logic driving gnutls_handshake is the same with the first
+	   and subsequent calls, we'll just fire the callback immediately to
+	   accomplish this.
+	*/
 	ssl_gnutls_handshake_cb(gsc, gsc->fd, PURPLE_INPUT_READ);
 }
 
--- a/libpurple/plugins/ssl/ssl-nss.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/plugins/ssl/ssl-nss.c	Mon Jun 18 01:48:35 2007 +0000
@@ -32,7 +32,6 @@
 #undef HAVE_LONG_LONG /* Make Mozilla less angry. If angry, Mozilla SMASH! */
 
 #include <nspr.h>
-#include <private/pprio.h>
 #include <nss.h>
 #include <pk11func.h>
 #include <prio.h>
@@ -42,6 +41,10 @@
 #include <sslerr.h>
 #include <sslproto.h>
 
+/* This is defined in NSPR's <private/pprio.h>, but to avoid including a
+ * private header we duplicate the prototype here */
+NSPR_API(PRFileDesc*)  PR_ImportTCPSocket(PRInt32 osfd);
+
 typedef struct
 {
 	PRFileDesc *fd;
@@ -311,8 +314,13 @@
 	if(!nss_data)
 		return;
 
-	if (nss_data->in) PR_Close(nss_data->in);
-	/* if (nss_data->fd) PR_Close(nss_data->fd); */
+	if (nss_data->in) {
+		PR_Close(nss_data->in);
+		gsc->fd = -1;
+	} else if (nss_data->fd) {
+		PR_Close(nss_data->fd);
+		gsc->fd = -1;
+	}
 
 	if (nss_data->handshake_handler)
 		purple_input_remove(nss_data->handshake_handler);
--- a/libpurple/plugins/tcl/tcl.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/plugins/tcl/tcl.c	Mon Jun 18 01:48:35 2007 +0000
@@ -457,11 +457,23 @@
 
 	if ((version = wpurple_read_reg_string(HKEY_LOCAL_MACHINE, regkey, "CurrentVersion"))
 			|| (version = wpurple_read_reg_string(HKEY_CURRENT_USER, regkey, "CurrentVersion"))) {
-		char *path;
+		char *path = NULL;
 		char *regkey2;
+		char **tokens;
+		int major = 0, minor = 0, micro = 0;
+
+		tokens = g_strsplit(version, ".", 0);
+		if (tokens[0] && tokens[1] && tokens[2]) {
+			major = atoi(tokens[0]);
+			minor = atoi(tokens[1]);
+			micro = atoi(tokens[2]);
+		}
+		g_strfreev(tokens);
 
 		regkey2 = g_strdup_printf("%s%s\\", regkey, version);
-		if ((path = wpurple_read_reg_string(HKEY_LOCAL_MACHINE, regkey2, NULL)) || (path = wpurple_read_reg_string(HKEY_CURRENT_USER, regkey2, NULL))) {
+		if (!(major == 8 && minor == 4 && micro >= 5))
+			purple_debug(PURPLE_DEBUG_INFO, "tcl", "Unsupported ActiveTCL version %s found.\n", version);
+		else if ((path = wpurple_read_reg_string(HKEY_LOCAL_MACHINE, regkey2, NULL)) || (path = wpurple_read_reg_string(HKEY_CURRENT_USER, regkey2, NULL))) {
 			char *tclpath;
 			char *tkpath;
 
--- a/libpurple/plugins/tcl/tcl_signals.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/plugins/tcl/tcl_signals.c	Mon Jun 18 01:48:35 2007 +0000
@@ -49,7 +49,9 @@
 
 	Tcl_DecrRefCount(handler->signal);
 	if (handler->namespace)
+	{
 		Tcl_DecrRefCount(handler->namespace);
+	}
 	g_free(handler);
 }
 
--- a/libpurple/protocols/Makefile.am	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/Makefile.am	Mon Jun 18 01:48:35 2007 +0000
@@ -1,5 +1,5 @@
 EXTRA_DIST = Makefile.mingw
 
-DIST_SUBDIRS = bonjour gg irc jabber msn novell oscar qq sametime silc toc simple yahoo zephyr
+DIST_SUBDIRS = bonjour gg irc jabber msn novell null oscar qq sametime silc silc10 toc simple yahoo zephyr
 
 SUBDIRS = $(DYNAMIC_PRPLS) $(STATIC_PRPLS)
--- a/libpurple/protocols/Makefile.mingw	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/Makefile.mingw	Mon Jun 18 01:48:35 2007 +0000
@@ -8,7 +8,7 @@
 PIDGIN_TREE_TOP := ../..
 include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
 
-SUBDIRS = gg irc jabber msn novell oscar qq sametime silc simple yahoo
+SUBDIRS = gg irc jabber msn novell null oscar qq sametime silc10 simple yahoo bonjour
 
 .PHONY: all install clean
 
--- a/libpurple/protocols/bonjour/Makefile.am	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/bonjour/Makefile.am	Mon Jun 18 01:48:35 2007 +0000
@@ -1,4 +1,6 @@
 EXTRA_DIST = \
+		mdns_win32.c \
+		mdns_win32.h \
 		Makefile.mingw
 
 pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
@@ -8,12 +10,16 @@
 	bonjour.h \
 	buddy.c \
 	buddy.h \
-	dns_sd.c \
-	dns_sd.h \
+	dns_sd_proxy.h \
 	jabber.c \
-	jabber.h
+	jabber.h \
+	mdns_common.c \
+	mdns_common.h \
+	mdns_howl.c \
+	mdns_howl.h \
+	mdns_types.h
 
-AM_CFLAGS = $(st)
+AM_CFLAGS = $(st) -DUSE_BONJOUR_HOWL
 
 libbonjour_la_LDFLAGS = -module -avoid-version
 
--- a/libpurple/protocols/bonjour/Makefile.mingw	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/bonjour/Makefile.mingw	Mon Jun 18 01:48:35 2007 +0000
@@ -8,7 +8,6 @@
 include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
 
 TARGET = libbonjour
-NEEDED_DLLS = $(HOWL_TOP)/bin/libhowl-1.dll
 TYPE = PLUGIN
 
 # Static or Plugin...
@@ -21,20 +20,22 @@
 endif
 endif
 
+CFLAGS += -DUSE_BONJOUR_APPLE
+
 ##
 ## INCLUDE PATHS
 ##
-INCLUDE_PATHS +=	-I$(BONJOUR_ROOT) \
+INCLUDE_PATHS +=	-I. \
 			-I$(GTK_TOP)/include \
 			-I$(GTK_TOP)/include/glib-2.0 \
 			-I$(GTK_TOP)/lib/glib-2.0/include \
-			-I$(HOWL_TOP)/include \
+			-I$(BONJOUR_TOP)/include \
 			-I$(PURPLE_TOP) \
 			-I$(PURPLE_TOP)/win32 \
 			-I$(PIDGIN_TREE_TOP)
 
 LIB_PATHS +=		-L$(GTK_TOP)/lib \
-			-L$(HOWL_TOP)/lib \
+			-L$(BONJOUR_TOP)/lib \
 			-L$(PURPLE_TOP)
 
 ##
@@ -42,7 +43,8 @@
 ##
 C_SRC =			bonjour.c \
 			buddy.c \
-			dns_sd.c \
+			mdns_common.c \
+			mdns_win32.c \
 			jabber.c
 
 OBJECTS = $(C_SRC:%.c=%.o)
@@ -54,7 +56,7 @@
 			-lglib-2.0 \
 			-lws2_32 \
 			-lintl \
-			-lhowl \
+			-ldnssd \
 			-lpurple
 
 include $(PIDGIN_COMMON_RULES)
@@ -68,7 +70,6 @@
 
 install: all $(DLL_INSTALL_DIR)
 	cp $(TARGET).dll $(DLL_INSTALL_DIR)
-	cp $(NEEDED_DLLS) $(PURPLE_INSTALL_DIR)
 
 $(OBJECTS): $(PURPLE_CONFIG_H)
 
--- a/libpurple/protocols/bonjour/bonjour.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/bonjour/bonjour.c	Mon Jun 18 01:48:35 2007 +0000
@@ -37,7 +37,7 @@
 #include "version.h"
 
 #include "bonjour.h"
-#include "dns_sd.h"
+#include "mdns_common.h"
 #include "jabber.h"
 #include "buddy.h"
 
@@ -94,14 +94,13 @@
 bonjour_login(PurpleAccount *account)
 {
 	PurpleConnection *gc = purple_account_get_connection(account);
-	PurpleGroup *bonjour_group = NULL;
-	BonjourData *bd = NULL;
+	PurpleGroup *bonjour_group;
+	BonjourData *bd;
 	PurpleStatus *status;
 	PurplePresence *presence;
 
 	gc->flags |= PURPLE_CONNECTION_HTML;
-	gc->proto_data = g_new0(BonjourData, 1);
-	bd = gc->proto_data;
+	gc->proto_data = bd = g_new0(BonjourData, 1);
 
 	/* Start waiting for jabber connections (iChat style) */
 	bd->jabber_data = g_new(BonjourJabber, 1);
@@ -111,26 +110,16 @@
 	if (bonjour_jabber_start(bd->jabber_data) == -1) {
 		/* Send a message about the connection error */
 		purple_connection_error(gc, _("Unable to listen for incoming IM connections\n"));
-
-		/* Free the data */
-		g_free(bd->jabber_data);
-		bd->jabber_data = NULL;
 		return;
 	}
 
 	/* Connect to the mDNS daemon looking for buddies in the LAN */
 	bd->dns_sd_data = bonjour_dns_sd_new();
-	bd->dns_sd_data->name = (sw_string)purple_account_get_username(account);
-	bd->dns_sd_data->txtvers = g_strdup("1");
-	bd->dns_sd_data->version = g_strdup("1");
 	bd->dns_sd_data->first = g_strdup(purple_account_get_string(account, "first", default_firstname));
 	bd->dns_sd_data->last = g_strdup(purple_account_get_string(account, "last", default_lastname));
 	bd->dns_sd_data->port_p2pj = bd->jabber_data->port;
-	bd->dns_sd_data->phsh = g_strdup("");
-	bd->dns_sd_data->email = g_strdup(purple_account_get_string(account, "email", ""));
-	bd->dns_sd_data->vc = g_strdup("");
-	bd->dns_sd_data->jid = g_strdup(purple_account_get_string(account, "jid", ""));
-	bd->dns_sd_data->AIM = g_strdup(purple_account_get_string(account, "AIM", ""));
+	/* Not engaged in AV conference */
+	bd->dns_sd_data->vc = g_strdup("!");
 
 	status = purple_account_get_active_status(account);
 	presence = purple_account_get_presence(account);
@@ -161,7 +150,7 @@
 bonjour_close(PurpleConnection *connection)
 {
 	PurpleGroup *bonjour_group;
-	BonjourData *bd = (BonjourData*)connection->proto_data;
+	BonjourData *bd = connection->proto_data;
 
 	/* Stop looking for buddies in the LAN */
 	if (bd->dns_sd_data != NULL)
@@ -278,6 +267,7 @@
 bonjour_convo_closed(PurpleConnection *connection, const char *who)
 {
 	PurpleBuddy *buddy = purple_find_buddy(connection->account, who);
+	BonjourBuddy *bb;
 
 	if (buddy == NULL)
 	{
@@ -288,7 +278,9 @@
 		return;
 	}
 
-	bonjour_jabber_close_conversation(((BonjourData*)(connection->proto_data))->jabber_data, buddy);
+	bb = buddy->proto_data;
+	bonjour_jabber_close_conversation(bb->conversation);
+	bb->conversation = NULL;
 }
 
 static char *
@@ -331,6 +323,8 @@
 static gboolean
 plugin_unload(PurplePlugin *plugin)
 {
+	/* These shouldn't happen here because they are allocated in _init() */
+
 	g_free(default_firstname);
 	g_free(default_lastname);
 	g_free(default_hostname);
@@ -491,8 +485,8 @@
 		LPUSER_INFO_10 user_info = NULL;
 		LPSERVER_INFO_100 server_info = NULL;
 		wchar_t *servername = NULL;
-		wchar_t username[UNLEN + 1] = {'\0'};
-		DWORD dwLenUsername = sizeof(username);
+		wchar_t username[UNLEN + 1];
+		DWORD dwLenUsername = UNLEN + 1;
 		FARPROC myNetServerEnum = wpurple_find_and_loadproc(
 			"Netapi32.dll", "NetServerEnum");
 		FARPROC myNetApiBufferFree = wpurple_find_and_loadproc(
@@ -517,7 +511,7 @@
 			}
 		}
 
-		if (!GetUserNameW(&username, &dwLenUsername)) {
+		if (!GetUserNameW((LPWSTR) &username, &dwLenUsername)) {
 			purple_debug_warning("bonjour",
 				"Unable to look up username\n");
 		}
@@ -553,7 +547,7 @@
 		 */
 		splitpoint = strchr(tmp, ',');
 		if (splitpoint != NULL)
-			default_lastname = g_strndup(tmp, splitpoint - tmp);			
+			default_lastname = g_strndup(tmp, splitpoint - tmp);
 		else
 			default_lastname = g_strdup(tmp);
 	}
--- a/libpurple/protocols/bonjour/bonjour.h	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/bonjour/bonjour.h	Mon Jun 18 01:48:35 2007 +0000
@@ -26,9 +26,7 @@
 #ifndef _BONJOUR_H_
 #define _BONJOUR_H_
 
-#include <howl.h>
-
-#include "dns_sd.h"
+#include "mdns_common.h"
 #include "internal.h"
 #include "jabber.h"
 
--- a/libpurple/protocols/bonjour/buddy.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/bonjour/buddy.c	Mon Jun 18 01:48:35 2007 +0000
@@ -27,51 +27,66 @@
  * Creates a new buddy.
  */
 BonjourBuddy *
-bonjour_buddy_new(const gchar *name, const gchar *first, gint port_p2pj,
-	const gchar *phsh, const gchar *status, const gchar *email,
-	const gchar *last, const gchar *jid, const gchar *AIM,
-	const gchar *vc, const gchar *ip, const gchar *msg)
+bonjour_buddy_new(const gchar *name, PurpleAccount* account)
 {
-	BonjourBuddy *buddy = malloc(sizeof(BonjourBuddy));
+	BonjourBuddy *buddy = g_new0(BonjourBuddy, 1);
 
+	buddy->account = account;
 	buddy->name = g_strdup(name);
-	buddy->first = g_strdup(first);
-	buddy->port_p2pj = port_p2pj;
-	buddy->phsh = g_strdup(phsh);
-	buddy->status = g_strdup(status);
-	buddy->email = g_strdup(email);
-	buddy->last = g_strdup(last);
-	buddy->jid = g_strdup(jid);
-	buddy->AIM = g_strdup(AIM);
-	buddy->vc = g_strdup(vc);
-	buddy->ip = g_strdup(ip);
-	buddy->msg = g_strdup(msg);
-	buddy->conversation = NULL;
 
 	return buddy;
 }
 
+void
+set_bonjour_buddy_value(BonjourBuddy* buddy, const char *record_key, const char *value, uint32_t len){
+	gchar **fld = NULL;
+
+	if (!strcmp(record_key, "1st"))
+		fld = &buddy->first;
+	else if(!strcmp(record_key, "email"))
+		fld = &buddy->email;
+	else if(!strcmp(record_key, "ext"))
+		fld = &buddy->ext;
+	else if(!strcmp(record_key, "jid"))
+		fld = &buddy->jid;
+	else if(!strcmp(record_key, "last"))
+		fld = &buddy->last;
+	else if(!strcmp(record_key, "msg"))
+		fld = &buddy->msg;
+	else if(!strcmp(record_key, "nick"))
+		fld = &buddy->nick;
+	else if(!strcmp(record_key, "node"))
+		fld = &buddy->node;
+	else if(!strcmp(record_key, "phsh"))
+		fld = &buddy->phsh;
+	else if(!strcmp(record_key, "status"))
+		fld = &buddy->status;
+	else if(!strcmp(record_key, "vc"))
+		fld = &buddy->vc;
+	else if(!strcmp(record_key, "ver"))
+		fld = &buddy->ver;
+	else if(!strcmp(record_key, "AIM"))
+		fld = &buddy->AIM;
+
+	if(fld == NULL)
+		return;
+
+	g_free(*fld);
+	*fld = NULL;
+	*fld = g_strndup(value, len);
+}
+
 /**
  * Check if all the compulsory buddy data is present.
  */
 gboolean
 bonjour_buddy_check(BonjourBuddy *buddy)
 {
-	if (buddy->name == NULL) {
+	if (buddy->account == NULL)
 		return FALSE;
-	}
-
-	if (buddy->first == NULL) {
-		return FALSE;
-	}
 
-	if (buddy->last == NULL) {
+	if (buddy->name == NULL)
 		return FALSE;
-	}
-
-	if (buddy->status == NULL) {
-		return FALSE;
-	}
 
 	return TRUE;
 }
@@ -82,12 +97,12 @@
  * the buddy.
  */
 void
-bonjour_buddy_add_to_purple(PurpleAccount *account, BonjourBuddy *bonjour_buddy)
+bonjour_buddy_add_to_purple(BonjourBuddy *bonjour_buddy)
 {
 	PurpleBuddy *buddy;
 	PurpleGroup *group;
 	const char *status_id, *first, *last;
-	char *alias;
+	gchar *alias;
 
 	/* Translate between the Bonjour status and the Purple status */
 	if (g_ascii_strcasecmp("dnd", bonjour_buddy->status) == 0)
@@ -117,10 +132,11 @@
 	}
 
 	/* Make sure the buddy exists in our buddy list */
-	buddy = purple_find_buddy(account, bonjour_buddy->name);
+	buddy = purple_find_buddy(bonjour_buddy->account, bonjour_buddy->name);
+
 	if (buddy == NULL)
 	{
-		buddy = purple_buddy_new(account, bonjour_buddy->name, alias);
+		buddy = purple_buddy_new(bonjour_buddy->account, bonjour_buddy->name, alias);
 		buddy->proto_data = bonjour_buddy;
 		purple_blist_node_set_flags((PurpleBlistNode *)buddy, PURPLE_BLIST_NODE_FLAG_NO_SAVE);
 		purple_blist_add_buddy(buddy, NULL, group, NULL);
@@ -128,13 +144,13 @@
 
 	/* Set the user's status */
 	if (bonjour_buddy->msg != NULL)
-		purple_prpl_got_user_status(account, buddy->name, status_id,
+		purple_prpl_got_user_status(bonjour_buddy->account, buddy->name, status_id,
 								  "message", bonjour_buddy->msg,
 								  NULL);
 	else
-		purple_prpl_got_user_status(account, buddy->name, status_id,
+		purple_prpl_got_user_status(bonjour_buddy->account, buddy->name, status_id,
 								  NULL);
-	purple_prpl_got_user_idle(account, buddy->name, FALSE, 0);
+	purple_prpl_got_user_idle(bonjour_buddy->account, buddy->name, FALSE, 0);
 
 	g_free(alias);
 }
@@ -146,6 +162,8 @@
 bonjour_buddy_delete(BonjourBuddy *buddy)
 {
 	g_free(buddy->name);
+	g_free(buddy->ip);
+
 	g_free(buddy->first);
 	g_free(buddy->phsh);
 	g_free(buddy->status);
@@ -154,14 +172,22 @@
 	g_free(buddy->jid);
 	g_free(buddy->AIM);
 	g_free(buddy->vc);
-	g_free(buddy->ip);
 	g_free(buddy->msg);
+	g_free(buddy->ext);
+	g_free(buddy->nick);
+	g_free(buddy->node);
+	g_free(buddy->ver);
 
-	if (buddy->conversation != NULL)
+	bonjour_jabber_close_conversation(buddy->conversation);
+	buddy->conversation = NULL;
+
+#ifdef USE_BONJOUR_APPLE
+	if (buddy->txt_query != NULL)
 	{
-		g_free(buddy->conversation->buddy_name);
-		g_free(buddy->conversation);
+		purple_input_remove(buddy->txt_query_fd);
+		DNSServiceRefDeallocate(buddy->txt_query);
 	}
+#endif
 
-	free(buddy);
+	g_free(buddy);
 }
--- a/libpurple/protocols/bonjour/buddy.h	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/bonjour/buddy.h	Mon Jun 18 01:48:35 2007 +0000
@@ -17,17 +17,27 @@
 #ifndef _BONJOUR_BUDDY
 #define _BONJOUR_BUDDY
 
-#include <howl.h>
 #include <glib.h>
 
+#include "config.h"
 #include "account.h"
 #include "jabber.h"
 
+#ifdef USE_BONJOUR_APPLE 
+#include "dns_sd_proxy.h"
+#else /* USE_BONJOUR_HOWL */
+#include <howl.h>
+#endif
+
 typedef struct _BonjourBuddy
 {
+	PurpleAccount *account;
+
 	gchar *name;
+	gchar *ip;
+	gint port_p2pj;
+
 	gchar *first;
-	gint port_p2pj;
 	gchar *phsh;
 	gchar *status;
 	gchar *email;
@@ -35,18 +45,49 @@
 	gchar *jid;
 	gchar *AIM;
 	gchar *vc;
-	gchar *ip;
 	gchar *msg;
+	gchar *ext;
+	gchar *nick;
+	gchar *node;
+	gchar *ver;
+
 	BonjourJabberConversation *conversation;
+
+#ifdef USE_BONJOUR_APPLE
+	DNSServiceRef txt_query;
+	int txt_query_fd;
+#endif
+
 } BonjourBuddy;
 
+static const char *const buddy_TXT_records[] = {
+	"1st",
+	"email",
+	"ext",
+	"jid",
+	"last",
+	"msg",
+	"nick",
+	"node",
+	"phsh",
+/*	"port.p2pj", Deprecated - MUST ignore */
+	"status",
+/*	"txtvers", Deprecated - hardcoded to 1 */
+	"vc",
+	"ver",
+	"AIM", /* non standard */
+	NULL
+};
+
 /**
  * Creates a new buddy.
  */
-BonjourBuddy *bonjour_buddy_new(const gchar *name, const gchar *first,
-	gint port_p2pj, const gchar *phsh, const gchar *status,
-	const gchar *email, const gchar *last, const gchar *jid,
-	const gchar *AIM, const gchar *vc, const gchar *ip, const gchar *msg);
+BonjourBuddy *bonjour_buddy_new(const gchar *name, PurpleAccount *account);
+
+/**
+ * Sets a value in the BonjourBuddy struct, destroying the old value
+ */
+void set_bonjour_buddy_value(BonjourBuddy* buddy, const char *record_key, const char *value, uint32_t len);
 
 /**
  * Check if all the compulsory buddy data is present.
@@ -56,7 +97,7 @@
 /**
  * If the buddy doesn't previoulsy exists, it is created. Else, its data is changed (???)
  */
-void bonjour_buddy_add_to_purple(PurpleAccount *account, BonjourBuddy *buddy);
+void bonjour_buddy_add_to_purple(BonjourBuddy *buddy);
 
 /**
  * Deletes a buddy from memory.
--- a/libpurple/protocols/bonjour/dns_sd.c	Thu Jun 14 19:48:48 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,387 +0,0 @@
-/*
- *  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 Library General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <string.h>
-
-#include "dns_sd.h"
-#include "bonjour.h"
-#include "buddy.h"
-#include "debug.h"
-
-/* Private functions */
-
-static sw_result HOWL_API
-_publish_reply(sw_discovery discovery, sw_discovery_oid oid,
-			   sw_discovery_publish_status status, sw_opaque extra)
-{
-	purple_debug_warning("bonjour", "_publish_reply --> Start\n");
-
-	/* Check the answer from the mDNS daemon */
-	switch (status)
-	{
-		case SW_DISCOVERY_PUBLISH_STARTED :
-			purple_debug_info("bonjour", "_publish_reply --> Service started\n");
-			break;
-		case SW_DISCOVERY_PUBLISH_STOPPED :
-			purple_debug_info("bonjour", "_publish_reply --> Service stopped\n");
-			break;
-		case SW_DISCOVERY_PUBLISH_NAME_COLLISION :
-			purple_debug_info("bonjour", "_publish_reply --> Name collision\n");
-			break;
-		case SW_DISCOVERY_PUBLISH_INVALID :
-			purple_debug_info("bonjour", "_publish_reply --> Service invalid\n");
-			break;
-	}
-
-	return SW_OKAY;
-}
-
-static sw_result HOWL_API
-_resolve_reply(sw_discovery discovery, sw_discovery_oid oid,
-			   sw_uint32 interface_index, sw_const_string name,
-			   sw_const_string type, sw_const_string domain,
-			   sw_ipv4_address address, sw_port port,
-			   sw_octets text_record, sw_ulong text_record_len,
-			   sw_opaque extra)
-{
-	BonjourBuddy *buddy;
-	PurpleAccount *account = (PurpleAccount*)extra;
-	gchar *txtvers = NULL;
-	gchar *version = NULL;
-	gchar *first = NULL;
-	gchar *phsh = NULL;
-	gchar *status = NULL;
-	gchar *email = NULL;
-	gchar *last = NULL;
-	gchar *jid = NULL;
-	gchar *AIM = NULL;
-	gchar *vc = NULL;
-	gchar *msg = NULL;
-	gint address_length = 16;
-	gchar *ip = NULL;
-	sw_text_record_iterator iterator;
-	char key[SW_TEXT_RECORD_MAX_LEN];
-	char value[SW_TEXT_RECORD_MAX_LEN];
-	sw_uint32 value_length;
-
-	sw_discovery_cancel(discovery, oid);
-
-	/* Get the ip as a string */
-	ip = malloc(address_length);
-	sw_ipv4_address_name(address, ip, address_length);
-
-	/* Obtain the parameters from the text_record */
-	if ((text_record_len > 0) && (text_record) && (*text_record != '\0'))
-	{
-		sw_text_record_iterator_init(&iterator, text_record, text_record_len);
-		while (sw_text_record_iterator_next(iterator, key, (sw_octet *)value, &value_length) == SW_OKAY)
-		{
-			/* Compare the keys with the possible ones and save them on */
-			/* the appropiate place of the buddy_list */
-			if (strcmp(key, "txtvers") == 0) {
-				txtvers = g_strdup(value);
-			} else if (strcmp(key, "version") == 0) {
-				version = g_strdup(value);
-			} else if (strcmp(key, "1st") == 0) {
-				first = g_strdup(value);
-			} else if (strcmp(key, "status") == 0) {
-				status = g_strdup(value);
-			} else if (strcmp(key, "email") == 0) {
-				email = g_strdup(value);
-			} else if (strcmp(key, "last") == 0) {
-				last = g_strdup(value);
-			} else if (strcmp(key, "jid") == 0) {
-				jid = g_strdup(value);
-			} else if (strcmp(key, "AIM") == 0) {
-				AIM = g_strdup(value);
-			} else if (strcmp(key, "vc") == 0) {
-				vc = g_strdup(value);
-			} else if (strcmp(key, "phsh") == 0) {
-				phsh = g_strdup(value);
-			} else if (strcmp(key, "msg") == 0) {
-				msg = g_strdup(value);
-			}
-		}
-	}
-
-	/* Put the parameters of the text_record in a buddy and add the buddy to */
-	/* the buddy list */
-	buddy = bonjour_buddy_new(name, first, port, phsh,
-							  status, email, last, jid, AIM, vc, ip, msg);
-
-	if (bonjour_buddy_check(buddy) == FALSE)
-	{
-		bonjour_buddy_delete(buddy);
-		return SW_DISCOVERY_E_UNKNOWN;
-	}
-
-	/* Add or update the buddy in our buddy list */
-	bonjour_buddy_add_to_purple(account, buddy);
-
-	/* Free all the temporal strings */
-	g_free(txtvers);
-	g_free(version);
-	g_free(first);
-	g_free(last);
-	g_free(status);
-	g_free(email);
-	g_free(jid);
-	g_free(AIM);
-	g_free(vc);
-	g_free(phsh);
-	g_free(msg);
-
-	return SW_OKAY;
-}
-
-static sw_result HOWL_API
-_browser_reply(sw_discovery discovery, sw_discovery_oid oid,
-			   sw_discovery_browse_status status,
-			   sw_uint32 interface_index, sw_const_string name,
-			   sw_const_string type, sw_const_string domain,
-			   sw_opaque_t extra)
-{
-	sw_discovery_resolve_id rid;
-	PurpleAccount *account = (PurpleAccount*)extra;
-	PurpleBuddy *gb = NULL;
-
-	switch (status)
-	{
-		case SW_DISCOVERY_BROWSE_INVALID:
-			purple_debug_warning("bonjour", "_browser_reply --> Invalid\n");
-			break;
-		case SW_DISCOVERY_BROWSE_RELEASE:
-			purple_debug_warning("bonjour", "_browser_reply --> Release\n");
-			break;
-		case SW_DISCOVERY_BROWSE_ADD_DOMAIN:
-			purple_debug_warning("bonjour", "_browser_reply --> Add domain\n");
-			break;
-		case SW_DISCOVERY_BROWSE_ADD_DEFAULT_DOMAIN:
-			purple_debug_warning("bonjour", "_browser_reply --> Add default domain\n");
-			break;
-		case SW_DISCOVERY_BROWSE_REMOVE_DOMAIN:
-			purple_debug_warning("bonjour", "_browser_reply --> Remove domain\n");
-			break;
-		case SW_DISCOVERY_BROWSE_ADD_SERVICE:
-			/* A new peer has joined the network and uses iChat bonjour */
-			purple_debug_info("bonjour", "_browser_reply --> Add service\n");
-			if (g_ascii_strcasecmp(name, account->username) != 0)
-			{
-				if (sw_discovery_resolve(discovery, interface_index, name, type,
-						domain, _resolve_reply, extra, &rid) != SW_OKAY)
-				{
-					purple_debug_warning("bonjour", "_browser_reply --> Cannot send resolve\n");
-				}
-			}
-			break;
-		case SW_DISCOVERY_BROWSE_REMOVE_SERVICE:
-			purple_debug_info("bonjour", "_browser_reply --> Remove service\n");
-			gb = purple_find_buddy((PurpleAccount*)extra, name);
-			if (gb != NULL)
-			{
-				bonjour_buddy_delete(gb->proto_data);
-				purple_blist_remove_buddy(gb);
-			}
-			break;
-		case SW_DISCOVERY_BROWSE_RESOLVED:
-			purple_debug_info("bonjour", "_browse_reply --> Resolved\n");
-			break;
-		default:
-			break;
-	}
-
-	return SW_OKAY;
-}
-
-static int
-_dns_sd_publish(BonjourDnsSd *data, PublishType type)
-{
-	sw_text_record dns_data;
-	sw_result publish_result = SW_OKAY;
-	char portstring[6];
-
-	/* Fill the data for the service */
-	if (sw_text_record_init(&dns_data) != SW_OKAY)
-	{
-		purple_debug_error("bonjour", "Unable to initialize the data for the mDNS.\n");
-		return -1;
-	}
-
-	/* Convert the port to a string */
-	snprintf(portstring, sizeof(portstring), "%d", data->port_p2pj);
-
-	/* Publish standard records */
-	sw_text_record_add_key_and_string_value(dns_data, "txtvers", data->txtvers);
-	sw_text_record_add_key_and_string_value(dns_data, "version", data->version);
-	sw_text_record_add_key_and_string_value(dns_data, "1st", data->first);
-	sw_text_record_add_key_and_string_value(dns_data, "last", data->last);
-	sw_text_record_add_key_and_string_value(dns_data, "port.p2pj", portstring);
-	sw_text_record_add_key_and_string_value(dns_data, "phsh", data->phsh);
-	sw_text_record_add_key_and_string_value(dns_data, "status", data->status);
-	sw_text_record_add_key_and_string_value(dns_data, "vc", data->vc);
-
-	/* Publish extra records */
-	if ((data->email != NULL) && (*data->email != '\0'))
-		sw_text_record_add_key_and_string_value(dns_data, "email", data->email);
-
-	if ((data->jid != NULL) && (*data->jid != '\0'))
-		sw_text_record_add_key_and_string_value(dns_data, "jid", data->jid);
-
-	if ((data->AIM != NULL) && (*data->AIM != '\0'))
-		sw_text_record_add_key_and_string_value(dns_data, "AIM", data->AIM);
-
-	if ((data->msg != NULL) && (*data->msg != '\0'))
-		sw_text_record_add_key_and_string_value(dns_data, "msg", data->msg);
-
-	/* Publish the service */
-	switch (type)
-	{
-		case PUBLISH_START:
-			publish_result = sw_discovery_publish(data->session, 0, data->name, ICHAT_SERVICE, NULL,
-								NULL, data->port_p2pj, sw_text_record_bytes(dns_data), sw_text_record_len(dns_data),
-								_publish_reply, NULL, &data->session_id);
-			break;
-		case PUBLISH_UPDATE:
-			publish_result = sw_discovery_publish_update(data->session, data->session_id,
-								sw_text_record_bytes(dns_data), sw_text_record_len(dns_data));
-			break;
-	}
-	if (publish_result != SW_OKAY)
-	{
-		purple_debug_error("bonjour", "Unable to publish or change the status of the _presence._tcp service.\n");
-		return -1;
-	}
-
-	/* Free the memory used by temp data */
-	sw_text_record_fina(dns_data);
-
-	return 0;
-}
-
-static void
-_dns_sd_handle_packets(gpointer data, gint source, PurpleInputCondition condition)
-{
-	sw_discovery_read_socket((sw_discovery)data);
-}
-
-/* End private functions */
-
-/**
- * Allocate space for the dns-sd data.
- */
-BonjourDnsSd *
-bonjour_dns_sd_new()
-{
-	BonjourDnsSd *data = g_new0(BonjourDnsSd, 1);
-
-	return data;
-}
-
-/**
- * Deallocate the space of the dns-sd data.
- */
-void
-bonjour_dns_sd_free(BonjourDnsSd *data)
-{
-	g_free(data->first);
-	g_free(data->last);
-	g_free(data->email);
-	g_free(data);
-}
-
-/**
- * Send a new dns-sd packet updating our status.
- */
-void
-bonjour_dns_sd_send_status(BonjourDnsSd *data, const char *status, const char *status_message)
-{
-	g_free(data->status);
-	g_free(data->msg);
-
-	data->status = g_strdup(status);
-	data->msg = g_strdup(status_message);
-
-	/* Update our text record with the new status */
-	_dns_sd_publish(data, PUBLISH_UPDATE); /* <--We must control the errors */
-}
-
-/**
- * Advertise our presence within the dns-sd daemon and start browsing
- * for other bonjour peers.
- */
-gboolean
-bonjour_dns_sd_start(BonjourDnsSd *data)
-{
-	PurpleAccount *account;
-	PurpleConnection *gc;
-	gint dns_sd_socket;
-	sw_discovery_oid session_id;
-
-	account = data->account;
-	gc = purple_account_get_connection(account);
-
-	/* Initialize the dns-sd data and session */
-	if (sw_discovery_init(&data->session) != SW_OKAY)
-	{
-		purple_debug_error("bonjour", "Unable to initialize an mDNS session.\n");
-
-		/* In Avahi, sw_discovery_init frees data->session but doesn't clear it */
-		data->session = NULL;
-
-		return FALSE;
-	}
-
-	/* Publish our bonjour IM client at the mDNS daemon */
-	_dns_sd_publish(data, PUBLISH_START); /* <--We must control the errors */
-
-	/* Advise the daemon that we are waiting for connections */
-	if (sw_discovery_browse(data->session, 0, ICHAT_SERVICE, NULL, _browser_reply,
-			data->account, &session_id) != SW_OKAY)
-	{
-		purple_debug_error("bonjour", "Unable to get service.");
-		return FALSE;
-	}
-
-	/* Get the socket that communicates with the mDNS daemon and bind it to a */
-	/* callback that will handle the dns_sd packets */
-	dns_sd_socket = sw_discovery_socket(data->session);
-	gc->inpa = purple_input_add(dns_sd_socket, PURPLE_INPUT_READ,
-									_dns_sd_handle_packets, data->session);
-
-	return TRUE;
-}
-
-/**
- * Unregister the "_presence._tcp" service at the mDNS daemon.
- */
-void
-bonjour_dns_sd_stop(BonjourDnsSd *data)
-{
-	PurpleAccount *account;
-	PurpleConnection *gc;
-
-	if (data->session == NULL)
-		return;
-
-	sw_discovery_cancel(data->session, data->session_id);
-
-	account = data->account;
-	gc = purple_account_get_connection(account);
-	purple_input_remove(gc->inpa);
-
-	g_free(data->session);
-	data->session = NULL;
-}
--- a/libpurple/protocols/bonjour/dns_sd.h	Thu Jun 14 19:48:48 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*
- *  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 Library General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _BONJOUR_DNS_SD
-#define _BONJOUR_DNS_SD
-
-#include <howl.h>
-#include <glib.h>
-#include "account.h"
-
-#define ICHAT_SERVICE "_presence._tcp."
-
-/**
- * Data to be used by the dns-sd connection.
- */
-typedef struct _BonjourDnsSd
-{
-	sw_discovery session;
-	sw_discovery_oid session_id;
-	PurpleAccount *account;
-	gchar *name;
-	gchar *txtvers;
-	gchar *version;
-	gchar *first;
-	gchar *last;
-	gint port_p2pj;
-	gchar *phsh;
-	gchar *status;
-	gchar *email;
-	gchar *vc;
-	gchar *jid;
-	gchar *AIM;
-	gchar *msg;
-	GHashTable *buddies;
-} BonjourDnsSd;
-
-typedef enum _PublishType {
-	PUBLISH_START,
-	PUBLISH_UPDATE
-} PublishType;
-
-/**
- * Allocate space for the dns-sd data.
- */
-BonjourDnsSd *bonjour_dns_sd_new(void);
-
-/**
- * Deallocate the space of the dns-sd data.
- */
-void bonjour_dns_sd_free(BonjourDnsSd *data);
-
-/**
- * Send a new dns-sd packet updating our status.
- */
-void bonjour_dns_sd_send_status(BonjourDnsSd *data, const char *status, const char *status_message);
-
-/**
- * Advertise our presence within the dns-sd daemon and start
- * browsing for other bonjour peers.
- */
-gboolean bonjour_dns_sd_start(BonjourDnsSd *data);
-
-/**
- * Unregister the "_presence._tcp" service at the mDNS daemon.
- */
-void bonjour_dns_sd_stop(BonjourDnsSd *data);
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/bonjour/dns_sd_proxy.h	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,19 @@
+#ifndef _DNS_SD_PROXY
+#define _DNS_SD_PROXY
+
+#include <stdint.h>
+
+/* fixup to make pidgin compile against win32 bonjour */
+#ifdef _WIN32
+#define _MSL_STDINT_H
+#undef bzero
+#endif
+
+#include <dns_sd.h>
+
+/* dns_sd.h defines bzero and we also do in libc_internal.h */
+#ifdef _WIN32
+#undef bzero
+#endif
+
+#endif
--- a/libpurple/protocols/bonjour/issues.txt	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/bonjour/issues.txt	Mon Jun 18 01:48:35 2007 +0000
@@ -6,4 +6,3 @@
 * Avatars
 * File transfers
 * Typing notifications
-* Check if it works on win32
--- a/libpurple/protocols/bonjour/jabber.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/bonjour/jabber.c	Mon Jun 18 01:48:35 2007 +0000
@@ -28,7 +28,6 @@
 #endif
 #include <sys/types.h>
 #include <glib.h>
-#include <glib/gprintf.h>
 #include <unistd.h>
 #include <fcntl.h>
 
@@ -45,29 +44,10 @@
 #include "bonjour.h"
 #include "buddy.h"
 
-static gint
-_connect_to_buddy(PurpleBuddy *gb)
-{
-	gint socket_fd;
-	gint retorno = 0;
-	struct sockaddr_in buddy_address;
-
-	/* Create a socket and make it non-blocking */
-	socket_fd = socket(PF_INET, SOCK_STREAM, 0);
-
-	buddy_address.sin_family = PF_INET;
-	buddy_address.sin_port = htons(((BonjourBuddy*)(gb->proto_data))->port_p2pj);
-	inet_aton(((BonjourBuddy*)(gb->proto_data))->ip, &(buddy_address.sin_addr));
-	memset(&(buddy_address.sin_zero), '\0', 8);
-
-	retorno = connect(socket_fd, (struct sockaddr*)&buddy_address, sizeof(struct sockaddr));
-	if (retorno == -1) {
-		purple_debug_warning("bonjour", "connect error: %s\n", strerror(errno));
-	}
-	fcntl(socket_fd, F_SETFL, O_NONBLOCK);
-
-	return socket_fd;
-}
+#define STREAM_END "</stream:stream>"
+/* TODO: specify version='1.0' and send stream features */
+#define DOCTYPE "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" \
+		"<stream:stream xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" from=\"%s\" to=\"%s\">"
 
 #if 0 /* this isn't used anywhere... */
 static const char *
@@ -94,6 +74,19 @@
 }
 #endif
 
+static BonjourJabberConversation *
+bonjour_jabber_conv_new() {
+
+	BonjourJabberConversation *bconv = g_new0(BonjourJabberConversation, 1);
+	bconv->socket = -1;
+	bconv->tx_buf = purple_circ_buffer_new(512);
+	bconv->tx_handler = -1;
+	bconv->rx_handler = -1;
+
+	return bconv;
+}
+
+
 static const char *
 _font_size_ichat_to_purple(int size)
 {
@@ -113,46 +106,34 @@
 
 	return "1";
 }
+
 static void
-_jabber_parse_and_write_message_to_ui(char *message, PurpleConnection *connection, PurpleBuddy *gb)
+_jabber_parse_and_write_message_to_ui(xmlnode *message_node, PurpleConnection *connection, PurpleBuddy *pb)
 {
-	xmlnode *body_node = NULL;
-	char *body = NULL;
-	xmlnode *html_node = NULL;
-	gboolean isHTML = FALSE;
-	xmlnode *html_body_node = NULL;
+	xmlnode *body_node, *html_node, *events_node;
+	char *body, *html_body = NULL;
 	const char *ichat_balloon_color = NULL;
 	const char *ichat_text_color = NULL;
-	xmlnode *html_body_font_node = NULL;
 	const char *font_face = NULL;
 	const char *font_size = NULL;
 	const char *font_color = NULL;
-	char *html_body = NULL;
-	xmlnode *events_node = NULL;
 	gboolean composing_event = FALSE;
-	gint garbage = -1;
-	xmlnode *message_node = NULL;
-
-	/* Parsing of the message */
-	message_node = xmlnode_from_str(message, strlen(message));
-	if (message_node == NULL) {
-		return;
-	}
 
 	body_node = xmlnode_get_child(message_node, "body");
-	if (body_node != NULL) {
-		body = xmlnode_get_data(body_node);
-	} else {
+	if (body_node == NULL)
 		return;
-	}
+	body = xmlnode_get_data(body_node);
 
 	html_node = xmlnode_get_child(message_node, "html");
 	if (html_node != NULL)
 	{
-		isHTML = TRUE;
+		xmlnode *html_body_node;
+
 		html_body_node = xmlnode_get_child(html_node, "body");
 		if (html_body_node != NULL)
 		{
+			xmlnode *html_body_font_node;
+
 			ichat_balloon_color = xmlnode_get_attrib(html_body_node, "ichatballooncolor");
 			ichat_text_color = xmlnode_get_attrib(html_body_node, "ichattextcolor");
 			html_body_font_node = xmlnode_get_child(html_body_node, "font");
@@ -162,36 +143,25 @@
 				/* The absolute iChat font sizes should be converted to 1..7 range */
 				font_size = xmlnode_get_attrib(html_body_font_node, "ABSZ");
 				if (font_size != NULL)
-				{
 					font_size = _font_size_ichat_to_purple(atoi(font_size));
-				}
 				font_color = xmlnode_get_attrib(html_body_font_node, "color");
 				html_body = xmlnode_get_data(html_body_font_node);
 				if (html_body == NULL)
-				{
 					/* This is the kind of formated messages that Purple creates */
-					html_body = xmlnode_to_str(html_body_font_node, &garbage);
-				}
-			} else {
-				isHTML = FALSE;
+					html_body = xmlnode_to_str(html_body_font_node, NULL);
 			}
-		} else {
-			isHTML = FALSE;
 		}
-
 	}
 
 	events_node = xmlnode_get_child_with_namespace(message_node, "x", "jabber:x:event");
 	if (events_node != NULL)
 	{
 		if (xmlnode_get_child(events_node, "composing") != NULL)
-		{
 			composing_event = TRUE;
-		}
 		if (xmlnode_get_child(events_node, "id") != NULL)
 		{
 			/* The user is just typing */
-			xmlnode_free(message_node);
+			/* TODO: Deal with typing notification */
 			g_free(body);
 			g_free(html_body);
 			return;
@@ -199,51 +169,51 @@
 	}
 
 	/* Compose the message */
-	if (isHTML)
+	if (html_body != NULL)
 	{
+		g_free(body);
+
 		if (font_face == NULL) font_face = "Helvetica";
 		if (font_size == NULL) font_size = "3";
 		if (ichat_text_color == NULL) ichat_text_color = "#000000";
 		if (ichat_balloon_color == NULL) ichat_balloon_color = "#FFFFFF";
-		body = g_strconcat("<font face='", font_face, "' size='", font_size, "' color='", ichat_text_color,
-							"' back='", ichat_balloon_color, "'>", html_body, "</font>", NULL);
+		body = g_strdup_printf("<font face='%s' size='%s' color='%s' back='%s'>%s</font>",
+				       font_face, font_size, ichat_text_color, ichat_balloon_color,
+				       html_body);
 	}
 
+	/* TODO: Should we do something with "composing_event" here? */
+
 	/* Send the message to the UI */
-	serv_got_im(connection, gb->name, body, 0, time(NULL));
+	serv_got_im(connection, pb->name, body, 0, time(NULL));
 
-	/* Free all the strings and nodes (the attributes are freed with their nodes) */
-	xmlnode_free(message_node);
 	g_free(body);
 	g_free(html_body);
 }
 
 struct _check_buddy_by_address_t {
-	char *address;
-	PurpleBuddy **gb;
+	const char *address;
+	PurpleBuddy **pb;
 	BonjourJabber *bj;
 };
 
 static void
 _check_buddy_by_address(gpointer key, gpointer value, gpointer data)
 {
-	PurpleBuddy *gb = (PurpleBuddy*)value;
+	PurpleBuddy *pb = value;
 	BonjourBuddy *bb;
-	struct _check_buddy_by_address_t *cbba;
-
-	gb = value;
-	cbba = data;
+	struct _check_buddy_by_address_t *cbba = data;
 
 	/*
 	 * If the current PurpleBuddy's data is not null and the PurpleBuddy's account
 	 * is the same as the account requesting the check then continue to determine
 	 * whether the buddies IP matches the target IP.
 	 */
-	if (cbba->bj->account == gb->account)
+	if (cbba->bj->account == pb->account)
 	{
-		bb = gb->proto_data;
+		bb = pb->proto_data;
 		if ((bb != NULL) && (g_ascii_strcasecmp(bb->ip, cbba->address) == 0))
-			*(cbba->gb) = gb;
+			*(cbba->pb) = pb;
 	}
 }
 
@@ -258,44 +228,116 @@
 	/* Read chunks of 512 bytes till the end of the data */
 	while ((partial_message_length = recv(socket, partial_data, 512, 0)) > 0)
 	{
-			g_string_append_len(data, partial_data, partial_message_length);
-			total_message_length += partial_message_length;
+		g_string_append_len(data, partial_data, partial_message_length);
+		total_message_length += partial_message_length;
 	}
 
 	if (partial_message_length == -1)
 	{
-		purple_debug_warning("bonjour", "receive error: %s\n", strerror(errno));
+		if (errno != EAGAIN)
+			purple_debug_warning("bonjour", "receive error: %s\n", strerror(errno));
 		if (total_message_length == 0) {
 			return -1;
 		}
 	}
 
-	*message = data->str;
-	g_string_free(data, FALSE);
+	*message = g_string_free(data, FALSE);
 	if (total_message_length != 0)
 		purple_debug_info("bonjour", "Receive: -%s- %d bytes\n", *message, total_message_length);
 
 	return total_message_length;
 }
 
-static gint
-_send_data(gint socket, char *message)
+static void
+_send_data_write_cb(gpointer data, gint source, PurpleInputCondition cond)
 {
-	gint message_len = strlen(message);
-	gint partial_sent = 0;
-	gchar *partial_message = message;
+	PurpleBuddy *pb = data;
+	BonjourBuddy *bb = pb->proto_data;
+	BonjourJabberConversation *bconv = bb->conversation;
+	int ret, writelen;
+
+	/* TODO: Make sure that the stream has been established before sending */
+
+	writelen = purple_circ_buffer_get_max_read(bconv->tx_buf);
+
+	if (writelen == 0) {
+		purple_input_remove(bconv->tx_handler);
+		bconv->tx_handler = -1;
+		return;
+	}
 
-	while ((partial_sent = send(socket, partial_message, message_len, 0)) < message_len)
-	{
-		if (partial_sent != -1) {
-			partial_message += partial_sent;
-			message_len -= partial_sent;
-		} else {
-			return -1;
-		}
+	ret = send(bconv->socket, bconv->tx_buf->outptr, writelen, 0);
+
+	if (ret < 0 && errno == EAGAIN)
+		return;
+	else if (ret <= 0) {
+		PurpleConversation *conv;
+		const char *error = strerror(errno);
+
+		purple_debug_error("bonjour", "Error sending message to buddy %s error: %s\n",
+				   purple_buddy_get_name(pb), error ? error : "(null)");
+
+		conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bb->name, pb->account);
+		if (conv != NULL)
+			purple_conversation_write(conv, NULL,
+				  _("Unable to send message."),
+				  PURPLE_MESSAGE_SYSTEM, time(NULL));
+
+		bonjour_jabber_close_conversation(bb->conversation);
+		bb->conversation = NULL;
+		return;
 	}
 
-	return strlen(message);
+	purple_circ_buffer_mark_read(bconv->tx_buf, ret);
+}
+
+static gint
+_send_data(PurpleBuddy *pb, char *message)
+{
+	gint ret;
+	int len = strlen(message);
+	BonjourBuddy *bb = pb->proto_data;
+	BonjourJabberConversation *bconv = bb->conversation;
+
+	/* If we're not ready to actually send, append it to the buffer */
+	if (bconv->tx_handler != -1
+			|| bconv->connect_data != NULL
+			|| !bconv->stream_started
+			|| purple_circ_buffer_get_max_read(bconv->tx_buf) > 0) {
+		ret = -1;
+		errno = EAGAIN;
+	} else {
+		ret = send(bconv->socket, message, len, 0);
+	}
+
+	if (ret == -1 && errno == EAGAIN)
+		ret = 0;
+	else if (ret <= 0) {
+		PurpleConversation *conv;
+		const char *error = strerror(errno);
+
+		purple_debug_error("bonjour", "Error sending message to buddy %s error: %s\n",
+				   purple_buddy_get_name(pb), error ? error : "(null)");
+
+		conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bb->name, pb->account);
+		if (conv != NULL)
+			purple_conversation_write(conv, NULL,
+				  _("Unable to send message."),
+				  PURPLE_MESSAGE_SYSTEM, time(NULL));
+
+		bonjour_jabber_close_conversation(bb->conversation);
+		bb->conversation = NULL;
+		return -1;
+	}
+
+	if (ret < len) {
+		if (bconv->tx_handler == -1)
+			bconv->tx_handler = purple_input_add(bconv->socket, PURPLE_INPUT_WRITE,
+				_send_data_write_cb, pb);
+		purple_circ_buffer_append(bconv->tx_buf, message + ret, len - ret);
+	}
+
+	return ret;
 }
 
 static void
@@ -303,17 +345,22 @@
 {
 	char *message = NULL;
 	gint message_length;
-	PurpleBuddy *gb = (PurpleBuddy*)data;
-	PurpleAccount *account = gb->account;
-	PurpleConversation *conversation;
-	char *closed_conv_message;
-	BonjourBuddy *bb = (BonjourBuddy*)gb->proto_data;
+	PurpleBuddy *pb = data;
+	PurpleAccount *account = pb->account;
+	BonjourBuddy *bb = pb->proto_data;
 	gboolean closed_conversation = FALSE;
-	xmlnode *message_node = NULL;
+	xmlnode *message_node;
 
 	/* Read the data from the socket */
 	if ((message_length = _read_data(socket, &message)) == -1) {
 		/* There have been an error reading from the socket */
+		if (errno != EAGAIN) {
+			bonjour_jabber_close_conversation(bb->conversation);
+			bb->conversation = NULL;
+
+			/* I guess we really don't need to notify the user.
+			 * If they try to send another message it'll reconnect */
+		}
 		return;
 	} else if (message_length == 0) { /* The other end has closed the socket */
 		closed_conversation = TRUE;
@@ -329,118 +376,184 @@
 	/* Parse the message into an XMLnode for analysis */
 	message_node = xmlnode_from_str(message, strlen(message));
 
-	/* Check if the start of the stream has been received, if not check that the current */
-	/* data is the start of the stream */
-	if (!(bb->conversation->stream_started))
-	{
-		/* Check if this is the start of the stream */
-		if ((message_node != NULL) &&
-		   g_ascii_strcasecmp(xmlnode_get_attrib(message_node, "xmlns"), "jabber:client") &&
-		   (xmlnode_get_attrib(message_node,"xmlns:stream") != NULL))
-		{
-			bb->conversation->stream_started = TRUE;
-		}
-		else
-		{
-			/* TODO: This needs to be nonblocking! */
-			if (send(bb->conversation->socket, DOCTYPE, strlen(DOCTYPE), 0) == -1)
-			{
-				purple_debug_error("bonjour", "Unable to start a conversation with %s\n", bb->name);
-			}
-			else
-			{
-				bb->conversation->stream_started = TRUE;
-			}
-		}
-	}
-
 	/*
 	 * Check that this is not the end of the conversation.  This is
 	 * using a magic string, but xmlnode won't play nice when just
 	 * parsing an end tag
 	 */
-	if (purple_str_has_prefix(message, STREAM_END) || (closed_conversation == TRUE)) {
+	if (closed_conversation || purple_str_has_prefix(message, STREAM_END)) {
+		PurpleConversation *conv;
+
 		/* Close the socket, clear the watcher and free memory */
-		if (bb->conversation != NULL) {
-			close(bb->conversation->socket);
-			purple_input_remove(bb->conversation->watcher_id);
-			g_free(bb->conversation->buddy_name);
-			g_free(bb->conversation);
-			bb->conversation = NULL;
-		}
+		bonjour_jabber_close_conversation(bb->conversation);
+		bb->conversation = NULL;
 
 		/* Inform the user that the conversation has been closed */
-		conversation = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, gb->name, account);
-		closed_conv_message = g_strdup_printf(_("%s has closed the conversation."), gb->name);
-		purple_conversation_write(conversation, NULL, closed_conv_message, PURPLE_MESSAGE_SYSTEM, time(NULL));
-		g_free(closed_conv_message);
+		conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, pb->name, account);
+		if (conv != NULL) {
+			char *tmp = g_strdup_printf(_("%s has closed the conversation."), pb->name);
+			purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL));
+			g_free(tmp);
+		}
+	} else if (message_node != NULL) {
+		/* Parse the message to get the data and send to the ui */
+		_jabber_parse_and_write_message_to_ui(message_node, account->gc, pb);
 	} else {
-		/* Parse the message to get the data and send to the ui */
-		_jabber_parse_and_write_message_to_ui(message, account->gc, gb);
+		/* TODO: Deal with receiving only a partial message */
 	}
 
+	g_free(message);
 	if (message_node != NULL)
 		xmlnode_free(message_node);
 }
 
+struct _stream_start_data {
+	char *msg;
+	PurpleInputFunction tx_handler_cb;
+};
+
+static void
+_start_stream(gpointer data, gint source, PurpleInputCondition condition)
+{
+	PurpleBuddy *pb = data;
+	BonjourBuddy *bb = pb->proto_data;
+	struct _stream_start_data *ss = bb->conversation->stream_data;
+	int len, ret;
+
+	len = strlen(ss->msg);
+
+	/* Start Stream */
+	ret = send(source, ss->msg, len, 0);
+
+	if (ret == -1 && errno == EAGAIN)
+		return;
+	else if (ret <= 0) {
+		const char *err = strerror(errno);
+		PurpleConversation *conv;
+
+		purple_debug_error("bonjour", "Error starting stream with buddy %s at %s:%d error: %s\n",
+				   purple_buddy_get_name(pb), bb->ip ? bb->ip : "(null)", bb->port_p2pj, err ? err : "(null)");
+
+		conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bb->name, pb->account);
+		if (conv != NULL)
+			purple_conversation_write(conv, NULL,
+				  _("Unable to send the message, the conversation couldn't be started."),
+				  PURPLE_MESSAGE_SYSTEM, time(NULL));
+
+		bonjour_jabber_close_conversation(bb->conversation);
+		bb->conversation = NULL;
+
+		return;
+	}
+
+	/* This is EXTREMELY unlikely to happen */
+	if (ret < len) {
+		char *tmp = g_strdup(ss->msg + ret);
+		g_free(ss->msg);
+		ss->msg = tmp;
+		return;
+	}
+
+	/* Stream started; process the send buffer if there is one*/
+	purple_input_remove(bb->conversation->tx_handler);
+	bb->conversation->tx_handler= -1;
+
+	bb->conversation->stream_started = TRUE;
+
+	g_free(ss->msg);
+	g_free(ss);
+	bb->conversation->stream_data = NULL;
+
+	if (ss->tx_handler_cb) {
+		bb->conversation->tx_handler = purple_input_add(source, PURPLE_INPUT_WRITE,
+			ss->tx_handler_cb, pb);
+		/* We can probably write the data now. */
+		(ss->tx_handler_cb)(pb, source, PURPLE_INPUT_WRITE);
+	}
+}
+
 static void
 _server_socket_handler(gpointer data, int server_socket, PurpleInputCondition condition)
 {
-	PurpleBuddy *gb = NULL;
+	PurpleBuddy *pb = NULL;
 	struct sockaddr_in their_addr; /* connector's address information */
 	socklen_t sin_size = sizeof(struct sockaddr);
 	int client_socket;
-	BonjourBuddy *bb = NULL;
-	BonjourJabber *bj = data;
+	BonjourBuddy *bb;
 	char *address_text = NULL;
 	PurpleBuddyList *bl = purple_get_blist();
 	struct _check_buddy_by_address_t *cbba;
 
 	/* Check that it is a read condition */
-	if (condition != PURPLE_INPUT_READ) {
+	if (condition != PURPLE_INPUT_READ)
 		return;
-	}
 
 	if ((client_socket = accept(server_socket, (struct sockaddr *)&their_addr, &sin_size)) == -1)
-	{
 		return;
-	}
+
 	fcntl(client_socket, F_SETFL, O_NONBLOCK);
 
 	/* Look for the buddy that has opened the conversation and fill information */
 	address_text = inet_ntoa(their_addr.sin_addr);
 	cbba = g_new0(struct _check_buddy_by_address_t, 1);
 	cbba->address = address_text;
-	cbba->gb = &gb;
-	cbba->bj = bj;
+	cbba->pb = &pb;
+	cbba->bj = data;
 	g_hash_table_foreach(bl->buddies, _check_buddy_by_address, cbba);
 	g_free(cbba);
-	if (gb == NULL)
+	if (pb == NULL)
 	{
 		purple_debug_info("bonjour", "We don't like invisible buddies, this is not a superheros comic\n");
 		close(client_socket);
 		return;
 	}
-	bb = (BonjourBuddy*)gb->proto_data;
+	bb = pb->proto_data;
 
 	/* Check if the conversation has been previously started */
 	if (bb->conversation == NULL)
 	{
-		bb->conversation = g_new(BonjourJabberConversation, 1);
+		int ret, len;
+		char *stream_start = g_strdup_printf(DOCTYPE, purple_account_get_username(pb->account),
+			purple_buddy_get_name(pb));
+
+		len = strlen(stream_start);
+
+		/* Start the stream */
+		ret = send(client_socket, stream_start, len, 0);
+
+		if (ret == -1 && errno == EAGAIN)
+			ret = 0;
+		else if (ret <= 0) {
+			const char *err = strerror(errno);
+
+			purple_debug_error("bonjour", "Error starting stream with buddy %s at %s:%d error: %s\n",
+					   purple_buddy_get_name(pb), bb->ip ? bb->ip : "(null)", bb->port_p2pj, err ? err : "(null)");
+
+			close(client_socket);
+			g_free(stream_start);
+
+			return;
+		}
+
+		bb->conversation = bonjour_jabber_conv_new();
 		bb->conversation->socket = client_socket;
-		bb->conversation->stream_started = FALSE;
-		bb->conversation->buddy_name = g_strdup(gb->name);
-		bb->conversation->message_id = 1;
+		bb->conversation->rx_handler = purple_input_add(client_socket,
+			PURPLE_INPUT_READ, _client_socket_handler, pb);
 
-		if (bb->conversation->stream_started == FALSE) {
-			/* Start the stream */
-			send(bb->conversation->socket, DOCTYPE, strlen(DOCTYPE), 0);
+		/* This is unlikely to happen */
+		if (ret < len) {
+			struct _stream_start_data *ss = g_new(struct _stream_start_data, 1);
+			ss->msg = g_strdup(stream_start + ret);
+			ss->tx_handler_cb = NULL; /* We have nothing to write yet */
+			bb->conversation->stream_data = ss;
+			/* Finish sending the stream start */
+			bb->conversation->tx_handler = purple_input_add(client_socket,
+				PURPLE_INPUT_WRITE, _start_stream, pb);
+		} else {
 			bb->conversation->stream_started = TRUE;
 		}
 
-		/* Open a watcher for the client socket */
-		bb->conversation->watcher_id = purple_input_add(client_socket, PURPLE_INPUT_READ,
-													_client_socket_handler, gb);
+		g_free(stream_start);
 	} else {
 		close(client_socket);
 	}
@@ -518,158 +631,224 @@
 	return data->port;
 }
 
+static void
+_connected_to_buddy(gpointer data, gint source, const gchar *error)
+{
+	PurpleBuddy *pb = data;
+	BonjourBuddy *bb = pb->proto_data;
+	int len, ret;
+	char *stream_start = g_strdup_printf(DOCTYPE, purple_account_get_username(pb->account), purple_buddy_get_name(pb));
+
+	bb->conversation->connect_data = NULL;
+
+	if (source < 0) {
+		PurpleConversation *conv;
+
+		purple_debug_error("bonjour", "Error connecting to buddy %s at %s:%d error: %s\n",
+				   purple_buddy_get_name(pb), bb->ip ? bb->ip : "(null)", bb->port_p2pj, error ? error : "(null)");
+
+		conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bb->name, pb->account);
+		if (conv != NULL)
+			purple_conversation_write(conv, NULL,
+				  _("Unable to send the message, the conversation couldn't be started."),
+				  PURPLE_MESSAGE_SYSTEM, time(NULL));
+
+		bonjour_jabber_close_conversation(bb->conversation);
+		bb->conversation = NULL;
+		return;
+	}
+
+	len = strlen(stream_start);
+
+	/* Start the stream and send queued messages */
+	ret = send(source, stream_start, len, 0);
+
+	if (ret == -1 && errno == EAGAIN)
+		ret = 0;
+	else if (ret <= 0) {
+		const char *err = strerror(errno);
+		PurpleConversation *conv;
+
+		purple_debug_error("bonjour", "Error starting stream with buddy %s at %s:%d error: %s\n",
+				   purple_buddy_get_name(pb), bb->ip ? bb->ip : "(null)", bb->port_p2pj, err ? err : "(null)");
+
+		conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bb->name, pb->account);
+		if (conv != NULL)
+			purple_conversation_write(conv, NULL,
+				  _("Unable to send the message, the conversation couldn't be started."),
+				  PURPLE_MESSAGE_SYSTEM, time(NULL));
+
+		close(source);
+		bonjour_jabber_close_conversation(bb->conversation);
+		bb->conversation = NULL;
+
+		g_free(stream_start);
+
+		return;
+	}
+
+	bb->conversation->socket = source;
+	bb->conversation->rx_handler = purple_input_add(source,
+		PURPLE_INPUT_READ, _client_socket_handler, pb);
+
+	/* This is unlikely to happen */
+	if (ret < len) {
+		struct _stream_start_data *ss = g_new(struct _stream_start_data, 1);
+		ss->msg = g_strdup(stream_start + ret);
+		ss->tx_handler_cb = _send_data_write_cb;
+		bb->conversation->stream_data = ss;
+		/* Finish sending the stream start */
+		bb->conversation->tx_handler = purple_input_add(source,
+			PURPLE_INPUT_WRITE, _start_stream, pb);
+	}
+	/* Process the send buffer */
+	else {
+		bb->conversation->stream_started = TRUE;
+		/* Watch for when we can write the buffered messages */
+		bb->conversation->tx_handler = purple_input_add(source, PURPLE_INPUT_WRITE,
+			_send_data_write_cb, pb);
+		/* We can probably write the data now. */
+		_send_data_write_cb(pb, source, PURPLE_INPUT_WRITE);
+	}
+
+	g_free(stream_start);
+}
+
 int
 bonjour_jabber_send_message(BonjourJabber *data, const gchar *to, const gchar *body)
 {
-	xmlnode *message_node = NULL;
-	gchar *message = NULL;
-	gint message_length = -1;
-	xmlnode *message_body_node = NULL;
-	xmlnode *message_html_node = NULL;
-	xmlnode *message_html_body_node = NULL;
-	xmlnode *message_html_body_font_node = NULL;
-	xmlnode *message_x_node = NULL;
-	PurpleBuddy *gb = NULL;
-	BonjourBuddy *bb = NULL;
-	PurpleConversation *conversation = NULL;
-	char *message_from_ui = NULL;
-	char *stripped_message = NULL;
-	gint ret;
+	xmlnode *message_node, *node, *node2;
+	gchar *message;
+	PurpleBuddy *pb;
+	BonjourBuddy *bb;
+	int ret;
 
-	gb = purple_find_buddy(data->account, to);
-	if (gb == NULL)
+	pb = purple_find_buddy(data->account, to);
+	if (pb == NULL) {
+		purple_debug_info("bonjour", "Can't send a message to an offline buddy (%s).\n", to);
 		/* You can not send a message to an offline buddy */
 		return -10000;
-
-	bb = (BonjourBuddy *)gb->proto_data;
-
-	/* Enclose the message from the UI within a "font" node */
-	message_body_node = xmlnode_new("body");
-	stripped_message = purple_markup_strip_html(body);
-	xmlnode_insert_data(message_body_node, stripped_message, strlen(stripped_message));
-	g_free(stripped_message);
-
-	message_from_ui = g_strconcat("<font>", body, "</font>", NULL);
-	message_html_body_font_node = xmlnode_from_str(message_from_ui, strlen(message_from_ui));
-	g_free(message_from_ui);
-
-	message_html_body_node = xmlnode_new("body");
-	xmlnode_insert_child(message_html_body_node, message_html_body_font_node);
+	}
 
-	message_html_node = xmlnode_new("html");
-	xmlnode_set_attrib(message_html_node, "xmlns", "http://www.w3.org/1999/xhtml");
-	xmlnode_insert_child(message_html_node, message_html_body_node);
-
-	message_x_node = xmlnode_new("x");
-	xmlnode_set_attrib(message_x_node, "xmlns", "jabber:x:event");
-	xmlnode_insert_child(message_x_node, xmlnode_new("composing"));
-
-	message_node = xmlnode_new("message");
-	xmlnode_set_attrib(message_node, "to", ((BonjourBuddy*)(gb->proto_data))->name);
-	xmlnode_set_attrib(message_node, "from", data->account->username);
-	xmlnode_set_attrib(message_node, "type", "chat");
-	xmlnode_insert_child(message_node, message_body_node);
-	xmlnode_insert_child(message_node, message_html_node);
-	xmlnode_insert_child(message_node, message_x_node);
-
-	message = xmlnode_to_str(message_node, &message_length);
-	xmlnode_free(message_node);
+	bb = pb->proto_data;
 
 	/* Check if there is a previously open conversation */
 	if (bb->conversation == NULL)
 	{
-		bb->conversation = g_new(BonjourJabberConversation, 1);
-		bb->conversation->socket = _connect_to_buddy(gb);
-		bb->conversation->stream_started = FALSE;
-		bb->conversation->buddy_name = g_strdup(gb->name);
-		bb->conversation->watcher_id = purple_input_add(bb->conversation->socket,
-				PURPLE_INPUT_READ, _client_socket_handler, gb);
+		PurpleProxyConnectData *connect_data;
+		PurpleProxyInfo *proxy_info;
+
+		/* Make sure that the account always has a proxy of "none".
+		 * This is kind of dirty, but proxy_connect_none() isn't exposed. */
+		proxy_info = purple_account_get_proxy_info(data->account);
+		if (proxy_info == NULL) {
+			proxy_info = purple_proxy_info_new();
+			purple_account_set_proxy_info(data->account, proxy_info);
+		}
+		purple_proxy_info_set_type(proxy_info, PURPLE_PROXY_NONE);
+
+		connect_data =
+			purple_proxy_connect(data->account->gc, data->account, bb->ip,
+					     bb->port_p2pj, _connected_to_buddy, pb);
+
+		if (connect_data == NULL) {
+			purple_debug_error("bonjour", "Unable to connect to buddy (%s).\n", to);
+			return -10001;
+		}
+
+		bb->conversation = bonjour_jabber_conv_new();
+		bb->conversation->connect_data = connect_data;
+		/* We don't want _send_data() to register the tx_handler;
+		 * that neeeds to wait until we're actually connected. */
+		bb->conversation->tx_handler = 0;
 	}
 
-	/* Check if the stream for the conversation has been started */
-	if (bb->conversation->stream_started == FALSE)
-	{
-		/* Start the stream */
-		if (send(bb->conversation->socket, DOCTYPE, strlen(DOCTYPE), 0) == -1)
-		{
-				purple_debug_error("bonjour", "Unable to start a conversation\n");
-				purple_debug_warning("bonjour", "send error: %s\n", strerror(errno));
-				conversation = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, bb->name, data->account);
-				purple_conversation_write(conversation, NULL, 
-										_("Unable to send the message, the conversation couldn't be started."),
-										PURPLE_MESSAGE_SYSTEM, time(NULL));
-				close(bb->conversation->socket);
-				purple_input_remove(bb->conversation->watcher_id);
+	message_node = xmlnode_new("message");
+	xmlnode_set_attrib(message_node, "to", bb->name);
+	xmlnode_set_attrib(message_node, "from", purple_account_get_username(data->account));
+	xmlnode_set_attrib(message_node, "type", "chat");
 
-				/* Free all the data related to the conversation */
-				g_free(bb->conversation->buddy_name);
-				g_free(bb->conversation);
-				bb->conversation = NULL;
-				g_free(message);
-				return 0;
-		}
-
-		bb->conversation->stream_started = TRUE;
-	}
-
-	/* Send the message */
-	ret = _send_data(bb->conversation->socket, message) == -1;
+	/* Enclose the message from the UI within a "font" node */
+	node = xmlnode_new_child(message_node, "body");
+	message = purple_markup_strip_html(body);
+	xmlnode_insert_data(node, message, strlen(message));
 	g_free(message);
 
-	if (ret == -1)
-		return -10000;
+	node = xmlnode_new_child(message_node, "html");
+	xmlnode_set_namespace(node, "http://www.w3.org/1999/xhtml");
+
+	node = xmlnode_new_child(node, "body");
+	message = g_strdup_printf("<font>%s</font>", body);
+	node2 = xmlnode_from_str(message, strlen(message));
+	g_free(message);
+	xmlnode_insert_child(node, node2);
 
-	return 1;
+	node = xmlnode_new_child(message_node, "x");
+	xmlnode_set_namespace(node, "jabber:x:event");
+	xmlnode_insert_child(node, xmlnode_new("composing"));
+
+	message = xmlnode_to_str(message_node, NULL);
+	xmlnode_free(message_node);
+
+	ret = _send_data(pb, message) >= 0;
+
+	g_free(message);
+
+	return ret;
 }
 
 void
-bonjour_jabber_close_conversation(BonjourJabber *data, PurpleBuddy *gb)
+bonjour_jabber_close_conversation(BonjourJabberConversation *bconv)
 {
-	BonjourBuddy *bb = (BonjourBuddy*)gb->proto_data;
-
-	if (bb->conversation != NULL)
+	if (bconv != NULL)
 	{
-		/* Send the end of the stream to the other end of the conversation */
-		send(bb->conversation->socket, STREAM_END, strlen(STREAM_END), 0);
-
 		/* Close the socket and remove the watcher */
-		close(bb->conversation->socket);
-		purple_input_remove(bb->conversation->watcher_id);
+		if (bconv->socket >= 0) {
+			/* Send the end of the stream to the other end of the conversation */
+			if (bconv->stream_started)
+				send(bconv->socket, STREAM_END, strlen(STREAM_END), 0);
+			/* TODO: We're really supposed to wait for "</stream:stream>" before closing the socket */
+			close(bconv->socket);
+		}
+		if (bconv->rx_handler != -1)
+			purple_input_remove(bconv->rx_handler);
+		if (bconv->tx_handler > 0)
+			purple_input_remove(bconv->tx_handler);
 
 		/* Free all the data related to the conversation */
-		g_free(bb->conversation->buddy_name);
-		g_free(bb->conversation);
-		bb->conversation = NULL;
+		purple_circ_buffer_destroy(bconv->tx_buf);
+		if (bconv->connect_data != NULL)
+			purple_proxy_connect_cancel(bconv->connect_data);
+		if (bconv->stream_data != NULL) {
+			struct _stream_start_data *ss = bconv->stream_data;
+			g_free(ss->msg);
+			g_free(ss);
+		}
+		g_free(bconv);
 	}
 }
 
 void
 bonjour_jabber_stop(BonjourJabber *data)
 {
-	PurpleBuddy *gb = NULL;
-	BonjourBuddy *bb = NULL;
-	GSList *buddies;
-	GSList *l;
+	/* Close the server socket and remove the watcher */
+	if (data->socket >= 0)
+		close(data->socket);
+	if (data->watcher_id > 0)
+		purple_input_remove(data->watcher_id);
 
-	/* Close the server socket and remove all the watcher */
-	close(data->socket);
-	purple_input_remove(data->watcher_id);
-
-	/* Close all the sockets and remove all the watchers after sending end streams */
+	/* Close all the conversation sockets and remove all the watchers after sending end streams */
 	if (data->account->gc != NULL)
 	{
-		buddies = purple_find_buddies(data->account, data->account->username);
-		for (l = buddies; l; l = l->next)
-		{
-			gb = (PurpleBuddy*)l->data;
-			bb = (BonjourBuddy*)gb->proto_data;
-			if (bb->conversation != NULL)
-			{
-				send(bb->conversation->socket, STREAM_END, strlen(STREAM_END), 0);
-				close(bb->conversation->socket);
-				purple_input_remove(bb->conversation->watcher_id);
-			}
+		GSList *buddies, *l;
+
+		buddies = purple_find_buddies(data->account, purple_account_get_username(data->account));
+		for (l = buddies; l; l = l->next) {
+			BonjourBuddy *bb = ((PurpleBuddy*) l->data)->proto_data;
+			bonjour_jabber_close_conversation(bb->conversation);
+			bb->conversation = NULL;
 		}
+
 		g_slist_free(buddies);
 	}
 }
--- a/libpurple/protocols/bonjour/jabber.h	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/bonjour/jabber.h	Mon Jun 18 01:48:35 2007 +0000
@@ -27,9 +27,7 @@
 #define _BONJOUR_JABBER_H_
 
 #include "account.h"
-
-#define STREAM_END "</stream:stream>"
-#define DOCTYPE "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<stream:stream xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\">"
+#include "circbuffer.h"
 
 typedef struct _BonjourJabber
 {
@@ -42,10 +40,12 @@
 typedef struct _BonjourJabberConversation
 {
 	gint socket;
-	gint watcher_id;
-	gchar* buddy_name;
+	guint rx_handler;
+	guint tx_handler;
+	PurpleCircBuffer *tx_buf;
 	gboolean stream_started;
-	gint message_id;
+	PurpleProxyConnectData *connect_data;
+	gpointer stream_data;
 } BonjourJabberConversation;
 
 /**
@@ -58,7 +58,7 @@
 
 int bonjour_jabber_send_message(BonjourJabber *data, const gchar *to, const gchar *body);
 
-void bonjour_jabber_close_conversation(BonjourJabber *data, PurpleBuddy *gb);
+void bonjour_jabber_close_conversation(BonjourJabberConversation *bconv);
 
 void bonjour_jabber_stop(BonjourJabber *data);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/bonjour/mdns_common.c	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,175 @@
+/*
+ *  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 Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+
+#include "config.h"
+#include "mdns_common.h"
+#include "bonjour.h"
+#include "buddy.h"
+#include "debug.h"
+
+
+/**
+ * Allocate space for the dns-sd data.
+ */
+BonjourDnsSd *
+bonjour_dns_sd_new()
+{
+	BonjourDnsSd *data = g_new0(BonjourDnsSd, 1);
+
+	return data;
+}
+
+/**
+ * Deallocate the space of the dns-sd data.
+ */
+void
+bonjour_dns_sd_free(BonjourDnsSd *data)
+{
+	g_free(data->first);
+	g_free(data->last);
+	g_free(data->phsh);
+	g_free(data->status);
+	g_free(data->vc);
+	g_free(data->msg);
+	g_free(data);
+}
+
+/**
+ * Send a new dns-sd packet updating our status.
+ */
+void
+bonjour_dns_sd_send_status(BonjourDnsSd *data, const char *status, const char *status_message)
+{
+	g_free(data->status);
+	g_free(data->msg);
+
+	data->status = g_strdup(status);
+	data->msg = g_strdup(status_message);
+
+	/* Update our text record with the new status */
+	_mdns_publish(data, PUBLISH_UPDATE); /* <--We must control the errors */
+}
+
+/**
+ * Advertise our presence within the dns-sd daemon and start browsing
+ * for other bonjour peers.
+ */
+gboolean
+bonjour_dns_sd_start(BonjourDnsSd *data)
+{
+	PurpleAccount *account;
+	PurpleConnection *gc;
+	gint dns_sd_socket;
+	gpointer opaque_data;
+
+#ifdef USE_BONJOUR_HOWL
+	sw_discovery_oid session_id;
+#endif
+
+	account = data->account;
+	gc = purple_account_get_connection(account);
+
+	/* Initialize the dns-sd data and session */
+#ifndef USE_BONJOUR_APPLE
+	if (sw_discovery_init(&data->session) != SW_OKAY)
+	{
+		purple_debug_error("bonjour", "Unable to initialize an mDNS session.\n");
+
+		/* In Avahi, sw_discovery_init frees data->session but doesn't clear it */
+		data->session = NULL;
+
+		return FALSE;
+	}
+#endif
+
+	/* Publish our bonjour IM client at the mDNS daemon */
+
+	if (0 != _mdns_publish(data, PUBLISH_START))
+	{
+		return FALSE;
+	}
+
+	/* Advise the daemon that we are waiting for connections */
+	
+#ifdef USE_BONJOUR_APPLE
+	if (DNSServiceBrowse(&data->browser, 0, 0, ICHAT_SERVICE, NULL, _mdns_service_browse_callback, account) 
+			!= kDNSServiceErr_NoError)
+#else /* USE_BONJOUR_HOWL */
+	if (sw_discovery_browse(data->session, 0, ICHAT_SERVICE, NULL, _browser_reply,
+			account, &session_id) != SW_OKAY)
+#endif
+	{
+		purple_debug_error("bonjour", "Unable to get service.");
+		return FALSE;
+	}
+
+	/* Get the socket that communicates with the mDNS daemon and bind it to a */
+	/* callback that will handle the dns_sd packets */
+
+#ifdef USE_BONJOUR_APPLE
+	dns_sd_socket = DNSServiceRefSockFD(data->browser);
+	opaque_data = data->browser;
+#else /* USE_BONJOUR_HOWL */
+	dns_sd_socket = sw_discovery_socket(data->session);
+	opaque_data = data->session;
+#endif
+
+	gc->inpa = purple_input_add(dns_sd_socket, PURPLE_INPUT_READ,
+				    _mdns_handle_event, opaque_data);
+
+	return TRUE;
+}
+
+/**
+ * Unregister the "_presence._tcp" service at the mDNS daemon.
+ */
+
+void
+bonjour_dns_sd_stop(BonjourDnsSd *data)
+{
+	PurpleAccount *account;
+	PurpleConnection *gc;
+
+#ifdef USE_BONJOUR_APPLE
+	if (data->advertisement == NULL || data->browser == NULL)
+#else /* USE_BONJOUR_HOWL */
+	if (data->session == NULL)
+#endif
+		return;
+
+#ifdef USE_BONJOUR_HOWL
+	sw_discovery_cancel(data->session, data->session_id);
+#endif
+
+	account = data->account;
+	gc = purple_account_get_connection(account);
+	purple_input_remove(gc->inpa);
+
+#ifdef USE_BONJOUR_APPLE
+	/* hack: for win32, we need to stop listening to the advertisement pipe too */
+	purple_input_remove(data->advertisement_handler);
+
+	DNSServiceRefDeallocate(data->advertisement);
+	DNSServiceRefDeallocate(data->browser);
+	data->advertisement = NULL;
+	data->browser = NULL;
+#else /* USE_BONJOUR_HOWL */
+	g_free(data->session);
+	data->session = NULL;
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/bonjour/mdns_common.h	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,54 @@
+/*
+ *  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 Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _BONJOUR_MDNS_COMMON
+#define _BONJOUR_MDNS_COMMON
+
+#include "mdns_types.h"
+
+#ifdef USE_BONJOUR_APPLE
+#include "mdns_win32.h"
+#elif defined USE_BONJOUR_HOWL
+#include "mdns_howl.h"
+#endif
+
+/**
+ * Allocate space for the dns-sd data.
+ */
+BonjourDnsSd *bonjour_dns_sd_new(void);
+
+/**
+ * Deallocate the space of the dns-sd data.
+ */
+void bonjour_dns_sd_free(BonjourDnsSd *data);
+
+/**
+ * Send a new dns-sd packet updating our status.
+ */
+void bonjour_dns_sd_send_status(BonjourDnsSd *data, const char *status, const char *status_message);
+
+/**
+ * Advertise our presence within the dns-sd daemon and start
+ * browsing for other bonjour peers.
+ */
+gboolean bonjour_dns_sd_start(BonjourDnsSd *data);
+
+/**
+ * Unregister the "_presence._tcp" service at the mDNS daemon.
+ */
+void bonjour_dns_sd_stop(BonjourDnsSd *data);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/bonjour/mdns_howl.c	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,238 @@
+/*
+ *  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 Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "mdns_howl.h"
+
+#include "debug.h"
+#include "buddy.h"
+
+sw_result HOWL_API
+_publish_reply(sw_discovery discovery, sw_discovery_oid oid,
+			   sw_discovery_publish_status status, sw_opaque extra)
+{
+	purple_debug_warning("bonjour", "_publish_reply --> Start\n");
+
+	/* Check the answer from the mDNS daemon */
+	switch (status)
+	{
+		case SW_DISCOVERY_PUBLISH_STARTED :
+			purple_debug_info("bonjour", "_publish_reply --> Service started\n");
+			break;
+		case SW_DISCOVERY_PUBLISH_STOPPED :
+			purple_debug_info("bonjour", "_publish_reply --> Service stopped\n");
+			break;
+		case SW_DISCOVERY_PUBLISH_NAME_COLLISION :
+			purple_debug_info("bonjour", "_publish_reply --> Name collision\n");
+			break;
+		case SW_DISCOVERY_PUBLISH_INVALID :
+			purple_debug_info("bonjour", "_publish_reply --> Service invalid\n");
+			break;
+	}
+
+	return SW_OKAY;
+}
+
+sw_result HOWL_API
+_resolve_reply(sw_discovery discovery, sw_discovery_oid oid,
+			   sw_uint32 interface_index, sw_const_string name,
+			   sw_const_string type, sw_const_string domain,
+			   sw_ipv4_address address, sw_port port,
+			   sw_octets text_record, sw_ulong text_record_len,
+			   sw_opaque extra)
+{
+	BonjourBuddy *buddy;
+	PurpleAccount *account = (PurpleAccount*)extra;
+	gint address_length = 16;
+	sw_text_record_iterator iterator;
+	char key[SW_TEXT_RECORD_MAX_LEN];
+	char value[SW_TEXT_RECORD_MAX_LEN];
+	sw_uint32 value_length;
+
+	sw_discovery_cancel(discovery, oid);
+
+	/* create a buddy record */
+	buddy = bonjour_buddy_new(name, account);
+
+	/* Get the ip as a string */
+	buddy->ip = g_malloc(address_length);
+	sw_ipv4_address_name(address, buddy->ip, address_length);
+
+	buddy->port_p2pj = port;
+
+	/* Obtain the parameters from the text_record */
+	if ((text_record_len > 0) && (text_record) && (*text_record != '\0'))
+	{
+		sw_text_record_iterator_init(&iterator, text_record, text_record_len);
+		while (sw_text_record_iterator_next(iterator, key, (sw_octet *)value, &value_length) == SW_OKAY)
+			set_bonjour_buddy_value(buddy, key, value, value_length);
+
+		sw_text_record_iterator_fina(iterator);
+	}
+
+	if (!bonjour_buddy_check(buddy))
+	{
+		bonjour_buddy_delete(buddy);
+		return SW_DISCOVERY_E_UNKNOWN;
+	}
+
+	/* Add or update the buddy in our buddy list */
+	bonjour_buddy_add_to_purple(buddy);
+
+	return SW_OKAY;
+}
+
+sw_result HOWL_API
+_browser_reply(sw_discovery discovery, sw_discovery_oid oid,
+			   sw_discovery_browse_status status,
+			   sw_uint32 interface_index, sw_const_string name,
+			   sw_const_string type, sw_const_string domain,
+			   sw_opaque_t extra)
+{
+	sw_discovery_resolve_id rid;
+	PurpleAccount *account = (PurpleAccount*)extra;
+	PurpleBuddy *gb = NULL;
+
+	switch (status)
+	{
+		case SW_DISCOVERY_BROWSE_INVALID:
+			purple_debug_warning("bonjour", "_browser_reply --> Invalid\n");
+			break;
+		case SW_DISCOVERY_BROWSE_RELEASE:
+			purple_debug_warning("bonjour", "_browser_reply --> Release\n");
+			break;
+		case SW_DISCOVERY_BROWSE_ADD_DOMAIN:
+			purple_debug_warning("bonjour", "_browser_reply --> Add domain\n");
+			break;
+		case SW_DISCOVERY_BROWSE_ADD_DEFAULT_DOMAIN:
+			purple_debug_warning("bonjour", "_browser_reply --> Add default domain\n");
+			break;
+		case SW_DISCOVERY_BROWSE_REMOVE_DOMAIN:
+			purple_debug_warning("bonjour", "_browser_reply --> Remove domain\n");
+			break;
+		case SW_DISCOVERY_BROWSE_ADD_SERVICE:
+			/* A new peer has joined the network and uses iChat bonjour */
+			purple_debug_info("bonjour", "_browser_reply --> Add service\n");
+			if (g_ascii_strcasecmp(name, account->username) != 0)
+			{
+				if (sw_discovery_resolve(discovery, interface_index, name, type,
+						domain, _resolve_reply, extra, &rid) != SW_OKAY)
+				{
+					purple_debug_warning("bonjour", "_browser_reply --> Cannot send resolve\n");
+				}
+			}
+			break;
+		case SW_DISCOVERY_BROWSE_REMOVE_SERVICE:
+			purple_debug_info("bonjour", "_browser_reply --> Remove service\n");
+			gb = purple_find_buddy((PurpleAccount*)extra, name);
+			if (gb != NULL)
+			{
+				bonjour_buddy_delete(gb->proto_data);
+				purple_blist_remove_buddy(gb);
+			}
+			break;
+		case SW_DISCOVERY_BROWSE_RESOLVED:
+			purple_debug_info("bonjour", "_browse_reply --> Resolved\n");
+			break;
+		default:
+			break;
+	}
+
+	return SW_OKAY;
+}
+
+int
+_mdns_publish(BonjourDnsSd *data, PublishType type)
+{
+	sw_text_record dns_data;
+	sw_result publish_result = SW_OKAY;
+	char portstring[6];
+	const char *jid, *aim, *email;
+
+	/* Fill the data for the service */
+	if (sw_text_record_init(&dns_data) != SW_OKAY)
+	{
+		purple_debug_error("bonjour", "Unable to initialize the data for the mDNS.\n");
+		return -1;
+	}
+
+	/* Convert the port to a string */
+	snprintf(portstring, sizeof(portstring), "%d", data->port_p2pj);
+
+	jid = purple_account_get_string(data->account, "jid", NULL);
+	aim = purple_account_get_string(data->account, "AIM", NULL);
+	email = purple_account_get_string(data->account, "email", NULL);
+
+	/* We should try to follow XEP-0174, but some clients have "issues", so we humor them.
+	 * See http://telepathy.freedesktop.org/wiki/SalutInteroperability
+	 */
+
+	/* Needed by iChat */
+	sw_text_record_add_key_and_string_value(dns_data, "txtvers", "1");
+	/* Needed by Gaim/Pidgin <= 2.0.1 (remove at some point) */
+	sw_text_record_add_key_and_string_value(dns_data, "1st", data->first);
+	/* Needed by Gaim/Pidgin <= 2.0.1 (remove at some point) */
+	sw_text_record_add_key_and_string_value(dns_data, "last", data->last);
+	/* Needed by Adium */
+	sw_text_record_add_key_and_string_value(dns_data, "port.p2pj", portstring);
+	/* Needed by iChat, Gaim/Pidgin <= 2.0.1 */
+	sw_text_record_add_key_and_string_value(dns_data, "status", data->status);
+	/* Currently always set to "!" since we don't support AV and wont ever be in a conference */
+	sw_text_record_add_key_and_string_value(dns_data, "vc", data->vc);
+	sw_text_record_add_key_and_string_value(dns_data, "ver", VERSION);
+	if (email != NULL && *email != '\0')
+		sw_text_record_add_key_and_string_value(dns_data, "email", email);
+	if (jid != NULL && *jid != '\0')
+		sw_text_record_add_key_and_string_value(dns_data, "jid", jid);
+	/* Nonstandard, but used by iChat */
+	if (aim != NULL && *aim != '\0')
+		sw_text_record_add_key_and_string_value(dns_data, "AIM", aim);
+	if (data->msg != NULL && *data->msg != '\0')
+		sw_text_record_add_key_and_string_value(dns_data, "msg", data->msg);
+	if (data->phsh != NULL && *data->phsh != '\0')
+		sw_text_record_add_key_and_string_value(dns_data, "phsh", data->phsh);
+
+	/* TODO: ext, nick, node */
+
+	/* Publish the service */
+	switch (type)
+	{
+		case PUBLISH_START:
+			publish_result = sw_discovery_publish(data->session, 0, purple_account_get_username(data->account), ICHAT_SERVICE, NULL,
+								NULL, data->port_p2pj, sw_text_record_bytes(dns_data), sw_text_record_len(dns_data),
+								_publish_reply, NULL, &data->session_id);
+			break;
+		case PUBLISH_UPDATE:
+			publish_result = sw_discovery_publish_update(data->session, data->session_id,
+								sw_text_record_bytes(dns_data), sw_text_record_len(dns_data));
+			break;
+	}
+	if (publish_result != SW_OKAY)
+	{
+		purple_debug_error("bonjour", "Unable to publish or change the status of the _presence._tcp service.\n");
+		return -1;
+	}
+
+	/* Free the memory used by temp data */
+	sw_text_record_fina(dns_data);
+
+	return 0;
+}
+
+void
+_mdns_handle_event(gpointer data, gint source, PurpleInputCondition condition)
+{
+	sw_discovery_read_socket((sw_discovery)data);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/bonjour/mdns_howl.h	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,47 @@
+/*
+ *  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 Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _BONJOUR_MDNS_HOWL
+#define _BONJOUR_MDNS_HOWL
+
+#include "config.h"
+
+#ifdef USE_BONJOUR_HOWL
+
+#include <howl.h>
+#include <glib.h>
+#include "mdns_types.h"
+
+/* callback functions */
+
+sw_result HOWL_API _publish_reply(sw_discovery discovery, sw_discovery_oid oid, sw_discovery_publish_status status, sw_opaque extra);
+
+sw_result HOWL_API _resolve_reply(sw_discovery discovery, sw_discovery_oid oid, sw_uint32 interface_index, sw_const_string name,
+	sw_const_string type, sw_const_string domain, sw_ipv4_address address, sw_port port, sw_octets text_record, 
+	sw_ulong text_record_len, sw_opaque extra);
+
+sw_result HOWL_API _browser_reply(sw_discovery discovery, sw_discovery_oid oid, sw_discovery_browse_status status,
+	sw_uint32 interface_index, sw_const_string name, sw_const_string type, sw_const_string domain, sw_opaque_t extra);
+
+
+/* interface functions */
+
+int _mdns_publish(BonjourDnsSd *data, PublishType type);
+void _mdns_handle_event(gpointer data, gint source, PurpleInputCondition condition);
+
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/bonjour/mdns_types.h	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,63 @@
+/*
+ *  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 Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _BONJOUR_MDNS_TYPES
+#define _BONJOUR_MDNS_TYPES
+
+#include <glib.h>
+#include "account.h"
+#include "config.h"
+
+#ifdef USE_BONJOUR_APPLE
+#include "dns_sd_proxy.h"
+#else /* USE_BONJOUR_HOWL */
+#include <howl.h>
+#endif
+
+#define ICHAT_SERVICE "_presence._tcp."
+
+/**
+ * Data to be used by the dns-sd connection.
+ */
+typedef struct _BonjourDnsSd
+{
+#ifdef USE_BONJOUR_APPLE
+	DNSServiceRef advertisement;
+	DNSServiceRef browser;
+
+	int advertisement_handler; /* hack... windows bonjour is broken, so we have to have this */
+#else /* USE_BONJOUR_HOWL */
+	sw_discovery session;
+	sw_discovery_oid session_id;
+#endif
+
+	PurpleAccount *account;
+	gchar *first;
+	gchar *last;
+	gint port_p2pj;
+	gchar *phsh;
+	gchar *status;
+	gchar *vc;
+	gchar *msg;
+} BonjourDnsSd;
+
+typedef enum _PublishType {
+	PUBLISH_START,
+	PUBLISH_UPDATE
+} PublishType;
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/bonjour/mdns_win32.c	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,296 @@
+/*
+ *  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 Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "mdns_win32.h"
+
+#include "debug.h"
+
+/* data structure for the resolve callback */
+typedef struct _ResolveCallbackArgs
+{
+	DNSServiceRef resolver;
+	int resolver_fd;
+
+	PurpleDnsQueryData *query;
+	gchar *fqn;
+
+	BonjourBuddy* buddy;
+} ResolveCallbackArgs;
+
+static void
+_mdns_parse_text_record(BonjourBuddy* buddy, const char* record, uint16_t record_len)
+{
+	const char *txt_entry;
+	uint8_t txt_len;
+	int i;
+
+	for (i = 0; buddy_TXT_records[i] != NULL; i++) {
+		txt_entry = TXTRecordGetValuePtr(record_len, record, buddy_TXT_records[i], &txt_len);
+		if (txt_entry != NULL)
+			set_bonjour_buddy_value(buddy, buddy_TXT_records[i], txt_entry, txt_len);
+	}
+}
+
+static void DNSSD_API
+_mdns_text_record_query_callback(DNSServiceRef DNSServiceRef, DNSServiceFlags flags,
+	uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *fullname,
+	uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata,
+	uint32_t ttl, void *context)
+{
+	if (kDNSServiceErr_NoError != errorCode)
+		purple_debug_error("bonjour", "text record query - callback error.\n");
+	else if (flags & kDNSServiceFlagsAdd)
+	{
+		BonjourBuddy *buddy = (BonjourBuddy*)context;
+		_mdns_parse_text_record(buddy, rdata, rdlen);
+		bonjour_buddy_add_to_purple(buddy);
+	}
+}
+
+static void
+_mdns_resolve_host_callback(GSList *hosts, gpointer data, const char *error_message)
+{
+	ResolveCallbackArgs* args = (ResolveCallbackArgs*)data;
+
+	if (!hosts || !hosts->data)
+		purple_debug_error("bonjour", "host resolution - callback error.\n");
+	else
+	{
+		struct sockaddr_in *addr = (struct sockaddr_in*)g_slist_nth_data(hosts, 1);
+		BonjourBuddy* buddy = args->buddy;
+
+		buddy->ip = g_strdup(inet_ntoa(addr->sin_addr));
+
+		/* finally, set up the continuous txt record watcher, and add the buddy to purple */
+
+		if (kDNSServiceErr_NoError == DNSServiceQueryRecord(&buddy->txt_query, 0, 0, args->fqn,
+				kDNSServiceType_TXT, kDNSServiceClass_IN, _mdns_text_record_query_callback, buddy))
+		{
+			gint fd = DNSServiceRefSockFD(buddy->txt_query);
+			buddy->txt_query_fd = purple_input_add(fd, PURPLE_INPUT_READ, _mdns_handle_event, buddy->txt_query);
+
+			bonjour_buddy_add_to_purple(buddy);
+		}
+		else
+			bonjour_buddy_delete(buddy);
+
+	}
+
+	/* free the hosts list*/
+	g_slist_free(hosts);
+
+	/* free the remaining args memory */
+	purple_dnsquery_destroy(args->query);
+	g_free(args->fqn);
+	g_free(args);
+}
+
+static void DNSSD_API
+_mdns_service_resolve_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode,
+    const char *fullname, const char *hosttarget, uint16_t port, uint16_t txtLen, const char *txtRecord, void *context)
+{
+	ResolveCallbackArgs *args = (ResolveCallbackArgs*)context;
+
+	/* remove the input fd and destroy the service ref */
+	purple_input_remove(args->resolver_fd);
+	DNSServiceRefDeallocate(args->resolver);
+
+	if (kDNSServiceErr_NoError != errorCode)
+	{
+		purple_debug_error("bonjour", "service resolver - callback error.\n");
+		bonjour_buddy_delete(args->buddy);
+		g_free(args);
+	}
+	else
+	{
+		args->buddy->port_p2pj = ntohs(port);
+
+		/* parse the text record */
+		_mdns_parse_text_record(args->buddy, txtRecord, txtLen);
+
+		/* set more arguments, and start the host resolver */
+		args->fqn = g_strdup(fullname);
+
+		if (!(args->query =
+			purple_dnsquery_a(hosttarget, port, _mdns_resolve_host_callback, args)))
+		{
+			purple_debug_error("bonjour", "service resolver - host resolution failed.\n");
+			bonjour_buddy_delete(args->buddy);
+			g_free(args->fqn);
+			g_free(args);
+		}
+	}
+
+}
+
+static void DNSSD_API
+_mdns_service_register_callback(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode,
+    const char *name, const char *regtype, const char *domain, void *context)
+{
+	/* we don't actually care about anything said in this callback - this is only here because Bonjour for windows is broken */
+	if (kDNSServiceErr_NoError != errorCode)
+		purple_debug_error("bonjour", "service advertisement - callback error.\n");
+	else
+		purple_debug_info("bonjour", "service advertisement - callback.\n");
+}
+
+void DNSSD_API
+_mdns_service_browse_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
+    DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context)
+{
+	PurpleAccount *account = (PurpleAccount*)context;
+	PurpleBuddy *gb = NULL;
+
+	if (kDNSServiceErr_NoError != errorCode)
+		purple_debug_error("bonjour", "service browser - callback error");
+	else if (flags & kDNSServiceFlagsAdd)
+	{
+		/* A presence service instance has been discovered... check it isn't us! */
+		if (g_ascii_strcasecmp(serviceName, account->username) != 0)
+		{
+			/* OK, lets go ahead and resolve it to add to the buddy list */
+			ResolveCallbackArgs *args = g_new0(ResolveCallbackArgs, 1);
+			args->buddy = bonjour_buddy_new(serviceName, account);
+
+			if (kDNSServiceErr_NoError != DNSServiceResolve(&args->resolver, 0, 0, serviceName, regtype, replyDomain, _mdns_service_resolve_callback, args))
+			{
+				bonjour_buddy_delete(args->buddy);
+				g_free(args);
+				purple_debug_error("bonjour", "service browser - failed to resolve service.\n");
+			}
+			else
+			{
+				/* get a file descriptor for this service ref, and add it to the input list */
+				gint resolver_fd = DNSServiceRefSockFD(args->resolver);
+				args->resolver_fd = purple_input_add(resolver_fd, PURPLE_INPUT_READ, _mdns_handle_event, args->resolver);
+			}
+		}
+	}
+	else
+	{
+		/* A peer has sent a goodbye packet, remove them from the buddy list */
+		purple_debug_info("bonjour", "service browser - remove notification\n");
+		gb = purple_find_buddy(account, serviceName);
+		if (gb != NULL)
+		{
+			bonjour_buddy_delete(gb->proto_data);
+			purple_blist_remove_buddy(gb);
+		}
+	}
+}
+
+int
+_mdns_publish(BonjourDnsSd *data, PublishType type)
+{
+	TXTRecordRef dns_data;
+	char portstring[6];
+	int ret = 0;
+	const char *jid, *aim, *email;
+	DNSServiceErrorType set_ret;
+
+	TXTRecordCreate(&dns_data, 256, NULL);
+
+	/* Convert the port to a string */
+	snprintf(portstring, sizeof(portstring), "%d", data->port_p2pj);
+
+	jid = purple_account_get_string(data->account, "jid", NULL);
+	aim = purple_account_get_string(data->account, "AIM", NULL);
+	email = purple_account_get_string(data->account, "email", NULL);
+
+	/* We should try to follow XEP-0174, but some clients have "issues", so we humor them.
+	 * See http://telepathy.freedesktop.org/wiki/SalutInteroperability
+	 */
+
+	/* Needed by iChat */
+	set_ret = TXTRecordSetValue(&dns_data, "txtvers", 1, "1");
+	/* Needed by Gaim/Pidgin <= 2.0.1 (remove at some point) */
+	if (set_ret == kDNSServiceErr_NoError)
+		set_ret = TXTRecordSetValue(&dns_data, "1st", strlen(data->first), data->first);
+	/* Needed by Gaim/Pidgin <= 2.0.1 (remove at some point) */
+	if (set_ret == kDNSServiceErr_NoError)
+		set_ret = TXTRecordSetValue(&dns_data, "last", strlen(data->last), data->last);
+	/* Needed by Adium */
+	if (set_ret == kDNSServiceErr_NoError)
+		set_ret = TXTRecordSetValue(&dns_data, "port.p2pj", strlen(portstring), portstring);
+	/* Needed by iChat, Gaim/Pidgin <= 2.0.1 */
+	if (set_ret == kDNSServiceErr_NoError)
+		set_ret = TXTRecordSetValue(&dns_data, "status", strlen(data->status), data->status);
+	if (set_ret == kDNSServiceErr_NoError)
+		set_ret = TXTRecordSetValue(&dns_data, "ver", strlen(VERSION), VERSION);
+	/* Currently always set to "!" since we don't support AV and wont ever be in a conference */
+	if (set_ret == kDNSServiceErr_NoError)
+		set_ret = TXTRecordSetValue(&dns_data, "vc", strlen(data->vc), data->vc);
+	if (set_ret == kDNSServiceErr_NoError && email != NULL && *email != '\0')
+		set_ret = TXTRecordSetValue(&dns_data, "email", strlen(email), email);
+	if (set_ret == kDNSServiceErr_NoError && jid != NULL && *jid != '\0')
+		set_ret = TXTRecordSetValue(&dns_data, "jid", strlen(jid), jid);
+	/* Nonstandard, but used by iChat */
+	if (set_ret == kDNSServiceErr_NoError && aim != NULL && *aim != '\0')
+		set_ret = TXTRecordSetValue(&dns_data, "AIM", strlen(aim), aim);
+	if (set_ret == kDNSServiceErr_NoError && data->msg != NULL && *data->msg != '\0')
+		set_ret = TXTRecordSetValue(&dns_data, "msg", strlen(data->msg), data->msg);
+	if (set_ret == kDNSServiceErr_NoError && data->phsh != NULL && *data->phsh != '\0')
+		set_ret = TXTRecordSetValue(&dns_data, "phsh", strlen(data->phsh), data->phsh);
+
+	/* TODO: ext, nick, node */
+
+	if (set_ret != kDNSServiceErr_NoError)
+	{
+		purple_debug_error("bonjour", "Unable to allocate memory for text record.\n");
+		ret = -1;
+	}
+	else
+	{
+		DNSServiceErrorType err = kDNSServiceErr_NoError;
+
+		/* OK, we're done constructing the text record, (re)publish the service */
+
+		switch (type)
+		{
+			case PUBLISH_START:
+				err = DNSServiceRegister(&data->advertisement, 0, 0, purple_account_get_username(data->account), ICHAT_SERVICE,
+					NULL, NULL, htons(data->port_p2pj), TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data),
+					_mdns_service_register_callback, NULL);
+				break;
+
+			case PUBLISH_UPDATE:
+				err = DNSServiceUpdateRecord(data->advertisement, NULL, 0, TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data), 0);
+				break;
+		}
+
+		if (kDNSServiceErr_NoError != err)
+		{
+			purple_debug_error("bonjour", "Failed to publish presence service.\n");
+			ret = -1;
+		}
+		else if (PUBLISH_START == type)
+		{
+			/* hack: Bonjour on windows is broken. We don't care about the callback but we have to listen anyway */
+			gint advertisement_fd = DNSServiceRefSockFD(data->advertisement);
+			data->advertisement_handler = purple_input_add(advertisement_fd, PURPLE_INPUT_READ, _mdns_handle_event, data->advertisement);
+		}
+	}
+
+	/* Free the memory used by temp data */
+	TXTRecordDeallocate(&dns_data);
+	return ret;
+}
+
+void
+_mdns_handle_event(gpointer data, gint source, PurpleInputCondition condition)
+{
+	DNSServiceProcessResult((DNSServiceRef)data);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/bonjour/mdns_win32.h	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,40 @@
+/*
+ *  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 Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _BONJOUR_MDNS_WIN32
+#define _BONJOUR_MDNS_WIN32
+
+#ifdef USE_BONJOUR_APPLE
+
+#include <glib.h>
+#include "mdns_types.h"
+#include "buddy.h"
+#include "dnsquery.h"
+#include "dns_sd_proxy.h"
+
+/* Bonjour async callbacks */
+
+void DNSSD_API _mdns_service_browse_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex,
+    DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context);
+
+/* interface functions */
+
+int _mdns_publish(BonjourDnsSd *data, PublishType type);
+void _mdns_handle_event(gpointer data, gint source, PurpleInputCondition condition);
+
+#endif
+
+#endif
--- a/libpurple/protocols/gg/gg.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/gg/gg.c	Mon Jun 18 01:48:35 2007 +0000
@@ -253,8 +253,8 @@
 
 /*
  */
-/* static void ggp_callback_buddylist_save_ok(PurpleConnection *gc, gchar *file) {{{ */
-static void ggp_callback_buddylist_save_ok(PurpleConnection *gc, gchar *file)
+/* static void ggp_callback_buddylist_save_ok(PurpleConnection *gc, const char *file) {{{ */
+static void ggp_callback_buddylist_save_ok(PurpleConnection *gc, const char *file)
 {
 	PurpleAccount *account = purple_connection_get_account(gc);
 
@@ -277,7 +277,7 @@
 		purple_debug_error("gg", "Could not open file: %s\n", file);
 		purple_notify_error(account, _("Couldn't open file"), msg, NULL);
 		g_free(msg);
-		g_free(file);
+		g_free(buddylist);
 		return;
 	}
 
--- a/libpurple/protocols/irc/msgs.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/irc/msgs.c	Mon Jun 18 01:48:35 2007 +0000
@@ -369,6 +369,7 @@
 
 	if (!strcmp(name, "322")) {
 		PurpleRoomlistRoom *room;
+		char *topic;
 
 		if (!args[0] || !args[1] || !args[2] || !args[3])
 			return;
@@ -376,7 +377,9 @@
 		room = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM, args[1], NULL);
 		purple_roomlist_room_add_field(irc->roomlist, room, args[1]);
 		purple_roomlist_room_add_field(irc->roomlist, room, GINT_TO_POINTER(strtol(args[2], NULL, 10)));
-		purple_roomlist_room_add_field(irc->roomlist, room, args[3]);
+		topic = irc_mirc2txt(args[3]);
+		purple_roomlist_room_add_field(irc->roomlist, room, topic);
+		g_free(topic);
 		purple_roomlist_room_add(irc->roomlist, room);
 	}
 }
--- a/libpurple/protocols/irc/parse.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/irc/parse.c	Mon Jun 18 01:48:35 2007 +0000
@@ -402,6 +402,22 @@
 		switch (result[i]) {
 		case '\002':
 		case '\003':
+			/* Foreground color */
+			if (isdigit(result[i + 1]))
+				i++;
+			if (isdigit(result[i + 1]))
+				i++;
+			/* Optional comma and background color */
+			if (result[i + 1] == ',') {
+				i++;
+				if (isdigit(result[i + 1]))
+					i++;
+				if (isdigit(result[i + 1]))
+					i++;
+			}
+			/* Note that i still points to the last character
+			 * of the color selection string. */
+			continue;
 		case '\007':
 		case '\017':
 		case '\026':
--- a/libpurple/protocols/jabber/.todo	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/jabber/.todo	Mon Jun 18 01:48:35 2007 +0000
@@ -38,7 +38,7 @@
             formatted. enhancement-request so that the birthday field in the setinfo form would split up into relevant fields allowing for a strict syntax (like year--month--day or so, perhaps even dropdown menus)
         </note>
         <note priority="low" time="1037890968">
-            have set info pre-fill values from the server when no local vcard exists. this will help people migrating to gaim
+            have set info pre-fill values from the server when no local vcard exists. this will help people migrating to libpurple-based clients
         </note>
     </note>
     <note priority="verylow" time="1036044192">
--- a/libpurple/protocols/jabber/Makefile.am	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/jabber/Makefile.am	Mon Jun 18 01:48:35 2007 +0000
@@ -43,15 +43,12 @@
 if STATIC_JABBER
 
 st = -DPURPLE_STATIC_PRPL
-noinst_LIBRARIES = libjabber.a libxmpp.a
+noinst_LIBRARIES = libjabber.a
 pkg_LTLIBRARIES =
 
-libjabber_a_SOURCES = $(JABBERSOURCES)
+libjabber_a_SOURCES = $(JABBERSOURCES) libxmpp.c
 libjabber_a_CFLAGS  = $(AM_CFLAGS)
 
-libxmpp_a_SOURCES = libxmpp.c
-libxmpp_a_CFLAGS = $(AM_CFLAGS)
-
 else
 
 st =
--- a/libpurple/protocols/jabber/disco.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/jabber/disco.c	Mon Jun 18 01:48:35 2007 +0000
@@ -224,17 +224,17 @@
 		/* If the server supports JABBER_CAP_GOOGLE_ROSTER; we will have already requested it */
 		jabber_roster_request(js);
 	}
-	
+
 	/* Send initial presence; this will trigger receipt of presence for contacts on the roster */
 	gpresence = purple_account_get_presence(js->gc->account);
 	status = purple_presence_get_active_status(gpresence);
-	jabber_presence_send(js->gc->account, status);	
+	jabber_presence_send(js->gc->account, status);
 }
 
 static void
 jabber_disco_server_info_result_cb(JabberStream *js, xmlnode *packet, gpointer data)
 {
-  	xmlnode *query, *child;
+	xmlnode *query, *child;
 	const char *from = xmlnode_get_attrib(packet, "from");
 	const char *type = xmlnode_get_attrib(packet, "type");
 
@@ -257,7 +257,7 @@
 		return;
 	}
 
-	for (child = xmlnode_get_child(query, "identity"); child; 
+	for (child = xmlnode_get_child(query, "identity"); child;
 	     child = xmlnode_get_next_twin(child)) {
 		const char *category, *type, *name;
 		category = xmlnode_get_attrib(child, "category");
@@ -266,7 +266,7 @@
 		type = xmlnode_get_attrib(child, "type");
 		if (!type || strcmp(type, "im"))
 			continue;
-		
+
 		name = xmlnode_get_attrib(child, "name");
 		if (!name)
 			continue;
@@ -279,7 +279,7 @@
 		}
 	}
 
-	for (child = xmlnode_get_child(query, "feature"); child; 
+	for (child = xmlnode_get_child(query, "feature"); child;
 	     child = xmlnode_get_next_twin(child)) {
 		const char *var;
 		var = xmlnode_get_attrib(child, "var");
@@ -324,11 +324,16 @@
 	for(child = xmlnode_get_child(query, "item"); child;
 			child = xmlnode_get_next_twin(child)) {
 		JabberIq *iq;
-		const char *jid;
+		const char *jid, *node;
 
 		if(!(jid = xmlnode_get_attrib(child, "jid")))
 			continue;
 
+		/* we don't actually care about the specific nodes,
+		 * so we won't query them */
+		if((node = xmlnode_get_attrib(child, "node")))
+			continue;
+
 		iq = jabber_iq_new_query(js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#info");
 		xmlnode_set_attrib(iq->node, "to", jid);
 		jabber_iq_send(iq);
--- a/libpurple/protocols/jabber/jabber.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Mon Jun 18 01:48:35 2007 +0000
@@ -463,7 +463,11 @@
 	JabberStream *js = gc->proto_data;
 
 	if (source < 0) {
-		purple_connection_error(gc, _("Couldn't connect to host"));
+		gchar *tmp;
+		tmp = g_strdup_printf(_("Could not establish a connection with the server:\n%s"),
+				error);
+		purple_connection_error(gc, tmp);
+		g_free(tmp);
 		return;
 	}
 
@@ -1070,8 +1074,10 @@
 			/* lets make sure our buddy icon is up to date
 			 * before we go letting people know we're here */
 			img = purple_buddy_icons_find_account_icon(js->gc->account);
-			jabber_set_buddy_icon(js->gc, img);
-			purple_imgstore_unref(img);
+			if(NULL != img) {
+				jabber_set_buddy_icon(js->gc, img);
+				purple_imgstore_unref(img);
+			}
 
 			/* now we can alert the core that we're ready to send status */
 			purple_connection_set_state(js->gc, PURPLE_CONNECTED);
--- a/libpurple/protocols/jabber/libxmpp.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/jabber/libxmpp.c	Mon Jun 18 01:48:35 2007 +0000
@@ -64,7 +64,7 @@
 	jabber_set_info,				/* set_info */
 	jabber_send_typing,				/* send_typing */
 	jabber_buddy_get_info,			/* get_info */
-	jabber_presence_send,			/* set_away */
+	jabber_presence_send,			/* set_status */
 	jabber_idle_set,				/* set_idle */
 	NULL,							/* change_passwd */
 	jabber_roster_add_buddy,		/* add_buddy */
--- a/libpurple/protocols/jabber/message.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/jabber/message.c	Mon Jun 18 01:48:35 2007 +0000
@@ -544,7 +544,6 @@
 	char *buf;
 	char *xhtml;
 	char *resource;
-	char *c;
 
 	if(!who || !msg)
 		return 0;
--- a/libpurple/protocols/jabber/presence.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/jabber/presence.c	Mon Jun 18 01:48:35 2007 +0000
@@ -106,11 +106,12 @@
 		return;
 
 	disconnected = purple_account_is_disconnected(account);
-	primitive = purple_status_type_get_primitive(purple_status_get_type(status));
 
 	if(disconnected)
 		return;
 
+	primitive = purple_status_type_get_primitive(purple_status_get_type(status));
+
 	gc = purple_account_get_connection(account);
 	js = gc->proto_data;
 
@@ -378,8 +379,7 @@
 			} else if(xmlns && !strcmp(xmlns, "vcard-temp:x:update")) {
 				xmlnode *photo = xmlnode_get_child(y, "photo");
 				if(photo) {
-					if(avatar_hash)
-						g_free(avatar_hash);
+					g_free(avatar_hash);
 					avatar_hash = xmlnode_get_data(photo);
 				}
 			}
@@ -408,8 +408,7 @@
 			jabber_id_free(jid);
 			g_free(status);
 			g_free(room_jid);
-			if(avatar_hash)
-				g_free(avatar_hash);
+			g_free(avatar_hash);
 			return;
 		}
 
@@ -425,8 +424,7 @@
 				jabber_id_free(jid);
 				g_free(status);
 				g_free(room_jid);
-				if(avatar_hash)
-					g_free(avatar_hash);
+				g_free(avatar_hash);
 				return;
 			}
 
@@ -509,8 +507,7 @@
 			purple_debug_warning("jabber", "Got presence for unknown buddy %s on account %s (%x)",
 				buddy_name, purple_account_get_username(js->gc->account), js->gc->account);
 			jabber_id_free(jid);
-			if(avatar_hash)
-				g_free(avatar_hash);
+			g_free(avatar_hash);
 			g_free(buddy_name);
 			g_free(status);
 			return;
@@ -567,8 +564,7 @@
 	}
 	g_free(status);
 	jabber_id_free(jid);
-	if(avatar_hash)
-		g_free(avatar_hash);
+	g_free(avatar_hash);
 }
 
 void jabber_presence_subscription_set(JabberStream *js, const char *who, const char *type)
@@ -607,7 +603,7 @@
 				formatted_msg = NULL;
 
 			if(formatted_msg)
-				purple_markup_html_to_xhtml(formatted_msg, NULL, msg);
+				*msg = purple_markup_strip_html(formatted_msg);
 		}
 
 		if(priority)
--- a/libpurple/protocols/jabber/si.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/jabber/si.c	Mon Jun 18 01:48:35 2007 +0000
@@ -26,6 +26,7 @@
 #include "cipher.h"
 #include "debug.h"
 #include "ft.h"
+#include "request.h"
 #include "network.h"
 #include "notify.h"
 
@@ -104,6 +105,9 @@
 	jsx->connect_data = NULL;
 
 	if(source < 0) {
+		purple_debug_warning("jabber",
+				"si connection failed, jid was %s, host was %s, error was %s\n",
+				streamhost->jid, streamhost->host, error_message);
 		jsx->streamhosts = g_list_remove(jsx->streamhosts, streamhost);
 		g_free(streamhost->jid);
 		g_free(streamhost->host);
@@ -769,6 +773,36 @@
 	}
 }
 
+static void resource_select_cancel_cb(PurpleXfer *xfer, PurpleRequestFields *fields)
+{
+	purple_xfer_cancel_local(xfer);
+}
+
+static void do_transfer_send(PurpleXfer *xfer, const char *resource)
+{
+	JabberSIXfer *jsx = xfer->data;
+	char **who_v = g_strsplit(xfer->who, "/", 2);
+	char *who;
+
+	who = g_strdup_printf("%s/%s", who_v[0], resource);
+	g_strfreev(who_v);
+	g_free(xfer->who);
+	xfer->who = who;
+	jabber_disco_info_do(jsx->js, who,
+			jabber_si_xfer_send_disco_cb, xfer);
+}
+
+static void resource_select_ok_cb(PurpleXfer *xfer, PurpleRequestFields *fields)
+{
+	PurpleRequestField *field = purple_request_fields_get_field(fields, "resource");
+	int selected_id = purple_request_field_choice_get_value(field);
+	GList *labels = purple_request_field_choice_get_labels(field);
+
+	const char *selected_label = g_list_nth_data(labels, selected_id);
+
+	do_transfer_send(xfer, selected_label);
+}
+
 static void jabber_si_xfer_init(PurpleXfer *xfer)
 {
 	JabberSIXfer *jsx = xfer->data;
@@ -776,26 +810,65 @@
 	if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {
 		JabberBuddy *jb;
 		JabberBuddyResource *jbr = NULL;
+		char *resource;
+
+		if(NULL != (resource = jabber_get_resource(xfer->who))) {
+			/* they've specified a resource, no need to ask or
+			 * default or anything, just do it */
+
+			do_transfer_send(xfer, resource);
+			g_free(resource);
+		}
 
 		jb = jabber_buddy_find(jsx->js, xfer->who, TRUE);
-		/* XXX */
-		if(!jb)
-			return;
+
+		if(!jb || !jb->resources) {
+			/* no resources online, we're trying to send to someone
+			 * whose presence we're not subscribed to, or
+			 * someone who is offline.  Let's inform the user */
+			char *msg;
 
-		/* XXX: for now, send to the first resource available */
-		if(jb->resources != NULL) {
-			char **who_v = g_strsplit(xfer->who, "/", 2);
-			char *who;
+			if(!jb) {
+				msg = g_strdup_printf(_("Unable to send file to %s, invalid JID"), xfer->who);
+			} else if(jb->subscription & JABBER_SUB_TO) {
+				msg = g_strdup_printf(_("Unable to send file to %s, user is not online"), xfer->who);
+			} else {
+				msg = g_strdup_printf(_("Unable to send file to %s, not subscribed to user presence"), xfer->who);
+			}
+
+			purple_notify_error(jsx->js->gc, _("File Send Failed"), _("File Send Failed"), msg);
+			g_free(msg);
+		} else if(g_list_length(jb->resources) == 1) {
+			/* only 1 resource online (probably our most common case)
+			 * so no need to ask who to send to */
+			jbr = jb->resources->data;
+
+			do_transfer_send(xfer, jbr->name);
 
-			jbr = jabber_buddy_find_resource(jb, NULL);
-			who = g_strdup_printf("%s/%s", who_v[0], jbr->name);
-			g_strfreev(who_v);
-			g_free(xfer->who);
-			xfer->who = who;
-			jabber_disco_info_do(jsx->js, who,
-					jabber_si_xfer_send_disco_cb, xfer);
 		} else {
-			return; /* XXX: ick */
+			/* we've got multiple resources, we need to pick one to send to */
+			GList *l;
+			char *msg = g_strdup_printf(_("Please select which resource of %s you would like to send a file to"), xfer->who);
+			PurpleRequestFields *fields = purple_request_fields_new();
+			PurpleRequestField *field = purple_request_field_choice_new("resource", _("Resource"), 0);
+			PurpleRequestFieldGroup *group = purple_request_field_group_new(NULL);
+
+			for(l = jb->resources; l; l = l->next)
+			{
+				jbr = l->data;
+
+				purple_request_field_choice_add(field, jbr->name);
+			}
+
+			purple_request_field_group_add_field(group, field);
+
+			purple_request_fields_add_group(fields, group);
+
+			purple_request_fields(jsx->js->gc, _("Select a Resource"), msg, NULL, fields,
+					_("Send File"), G_CALLBACK(resource_select_ok_cb), _("Cancel"), G_CALLBACK(resource_select_cancel_cb),
+					jsx->js->gc->account, xfer->who, NULL, xfer);
+
+			g_free(msg);
 		}
 	} else {
 		xmlnode *si, *feature, *x, *field, *value;
--- a/libpurple/protocols/msn/msn.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/msn/msn.c	Mon Jun 18 01:48:35 2007 +0000
@@ -1423,6 +1423,22 @@
 	if (found) \
 		sect_info = TRUE;
 
+#define MSN_GOT_INFO_GET_FIELD_NO_SEARCH(a, b) \
+	found = purple_markup_extract_info_field(stripped, stripped_len, user_info, \
+			"\n" a ":", 0, "\n", 0, "Undisclosed", b, 0, NULL, msn_info_strip_search_link); \
+	if (found) \
+		sect_info = TRUE;
+
+static char *
+msn_info_strip_search_link(const char *field, size_t len)
+{
+	const char *c;
+	if ((c = strstr(field, " (http://spaces.live.com/default.aspx?page=searchresults")) == NULL &&
+		(c = strstr(field, " (http://spaces.msn.com/default.aspx?page=searchresults")) == NULL)
+		return g_strndup(field, len);
+	return g_strndup(field, c - field);
+}
+
 static void
 msn_got_info(PurpleUtilFetchUrlData *url_data, gpointer data,
 		const gchar *url_text, size_t len, const gchar *error_message)
@@ -1538,10 +1554,10 @@
 	
 	/* General */
 	MSN_GOT_INFO_GET_FIELD("Nickname", _("Nickname"));
-	MSN_GOT_INFO_GET_FIELD("Age", _("Age"));
-	MSN_GOT_INFO_GET_FIELD("Gender", _("Gender"));
-	MSN_GOT_INFO_GET_FIELD("Occupation", _("Occupation"));
-	MSN_GOT_INFO_GET_FIELD("Location", _("Location"));
+	MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Age", _("Age"));
+	MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Gender", _("Gender"));
+	MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Occupation", _("Occupation"));
+	MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Location", _("Location"));
 
 	/* Extract their Interests and put it in */
 	found = purple_markup_extract_info_field(stripped, stripped_len, user_info,
@@ -1802,7 +1818,10 @@
 		/* This doesn't work with the new spaces profiles - Stu 3/2/06
 		char *p = strstr(url_buffer, "Unknown Member </TITLE>");
 		 * This might not work for long either ... */
+		/* Nope, it failed some time before 5/2/07 :(
 		char *p = strstr(url_buffer, "form id=\"SpacesSearch\" name=\"SpacesSearch\"");
+		 * Let's see how long this one holds out for ... */
+		char *p = strstr(url_buffer, "<form id=\"profile_form\" name=\"profile_form\" action=\"http&#58;&#47;&#47;spaces.live.com&#47;profile.aspx&#63;cid&#61;0\"");
 		PurpleBuddy *b = purple_find_buddy
 				(purple_connection_get_account(info_data->gc), info_data->name);
 		purple_notify_user_info_add_pair(user_info, _("Error retrieving profile"),
--- a/libpurple/protocols/msn/msn.h	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/msn/msn.h	Mon Jun 18 01:48:35 2007 +0000
@@ -67,7 +67,7 @@
 
 #define HOTMAIL_URL "http://www.hotmail.com/cgi-bin/folders"
 #define PASSPORT_URL "http://lc1.law13.hotmail.passport.com/cgi-bin/dologin?login="
-#define PROFILE_URL "http://spaces.msn.com/profile.aspx?mem="
+#define PROFILE_URL "http://spaces.live.com/profile.aspx?mem="
 
 #define USEROPT_HOTMAIL 0
 
--- a/libpurple/protocols/msn/nexus.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/msn/nexus.c	Mon Jun 18 01:48:35 2007 +0000
@@ -247,6 +247,8 @@
 				temp = g_strndup(error, c - error);
 				error = purple_url_decode(temp);
 				g_free(temp);
+				if ((temp = strstr(error, " Do one of the following or try again:")) != NULL)
+					*temp = '\0';
 			}
 		}
 
--- a/libpurple/protocols/msn/notification.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/msn/notification.c	Mon Jun 18 01:48:35 2007 +0000
@@ -591,12 +591,23 @@
 static void
 qng_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
+	MsnSession *session;
 	static int count = 0;
-	MsnSession *session = cmdproc->session;
+	const char *passport;
+	PurpleAccount *account;
+
+	session = cmdproc->session;
+	account = session->account;
 
 	if (session->passport_info.file == NULL)
 		return;
 
+	passport = purple_normalize(account, purple_account_get_username(account));
+
+	if ((strstr(passport, "@hotmail.") != NULL) ||
+		(strstr(passport, "@msn.com") != NULL))
+		return;
+
 	if (count++ < 26)
 		return;
 
@@ -901,6 +912,7 @@
 syn_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
 {
 	MsnSession *session;
+	MsnSync *sync;
 	int total_users;
 
 	session = cmdproc->session;
@@ -919,22 +931,12 @@
 
 	total_users  = atoi(cmd->params[2]);
 
-	if (total_users == 0)
-	{
-		msn_session_finish_login(session);
-	}
-	else
-	{
-		/* syn_table */
-		MsnSync *sync;
+	sync = msn_sync_new(session);
+	sync->total_users = total_users;
+	sync->old_cbs_table = cmdproc->cbs_table;
 
-		sync = msn_sync_new(session);
-		sync->total_users = total_users;
-		sync->old_cbs_table = cmdproc->cbs_table;
-
-		session->sync = sync;
-		cmdproc->cbs_table = sync->cbs_table;
-	}
+	session->sync = sync;
+	cmdproc->cbs_table = sync->cbs_table;
 }
 
 /**************************************************************************
--- a/libpurple/protocols/msn/servconn.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/msn/servconn.c	Mon Jun 18 01:48:35 2007 +0000
@@ -195,6 +195,7 @@
 	}
 	else
 	{
+		purple_debug_error("msn", "Connection error: %s\n", error_message);
 		msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_CONNECT);
 	}
 }
@@ -351,7 +352,7 @@
 
 		if (ret < 0 && errno == EAGAIN)
 			ret = 0;
-		if (ret < len) {
+		if (ret >= 0 && ret < len) {
 			if (servconn->tx_handler == -1)
 				servconn->tx_handler = purple_input_add(
 					servconn->fd, PURPLE_INPUT_WRITE,
--- a/libpurple/protocols/msn/session.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/msn/session.c	Mon Jun 18 01:48:35 2007 +0000
@@ -316,6 +316,7 @@
 							 "temporarily."));
 			break;
 		case MSN_ERROR_AUTH:
+			gc->wants_to_die = TRUE;
 			msg = g_strdup_printf(_("Unable to authenticate: %s"),
 								  (info == NULL ) ?
 								  _("Unknown error") : info);
@@ -385,6 +386,7 @@
 	PurpleAccount *account;
 	PurpleConnection *gc;
 	PurpleStoredImage *img;
+	const char *passport;
 
 	if (session->logged_in)
 		return;
@@ -408,5 +410,12 @@
 	 * and @msn.com accounts don't automatically get the initial email
 	 * notification so we always request it on login
 	 */
-	msn_cmdproc_send(session->notification->cmdproc, "URL", "%s", "INBOX");
+
+	passport = purple_normalize(account, purple_account_get_username(account));
+
+	if ((strstr(passport, "@hotmail.") != NULL) ||
+		(strstr(passport, "@msn.com") != NULL))
+	{
+		msn_cmdproc_send(session->notification->cmdproc, "URL", "%s", "INBOX");
+	}
 }
--- a/libpurple/protocols/msn/switchboard.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/msn/switchboard.c	Mon Jun 18 01:48:35 2007 +0000
@@ -419,7 +419,14 @@
 				case MSN_SB_ERROR_TOO_FAST:
 					str_reason = _("Message could not be sent "
 								   "because we are sending too quickly:");
-					break;					
+					break;
+				case MSN_SB_ERROR_AUTHFAILED:
+					str_reason = _("Message could not be sent "
+								   "because we wer unable to establish a "
+								   "session with the server. This is "
+								   "likely a server problem, try again in "
+								   "a few minutes:");
+					break;
 				default:
 					str_reason = _("Message could not be sent "
 								   "because an error with "
@@ -963,9 +970,13 @@
  * Connect stuff
  **************************************************************************/
 static void
+ans_usr_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error);
+
+static void
 connect_cb(MsnServConn *servconn)
 {
 	MsnSwitchBoard *swboard;
+	MsnTransaction *trans;
 	MsnCmdProc *cmdproc;
 	PurpleAccount *account;
 
@@ -980,16 +991,44 @@
 	{
 		swboard->empty = FALSE;
 
-		msn_cmdproc_send(cmdproc, "ANS", "%s %s %s",
-						 purple_account_get_username(account),
-						 swboard->auth_key, swboard->session_id);
+		trans = msn_transaction_new(cmdproc, "ANS", "%s %s %s",
+									purple_account_get_username(account),
+									swboard->auth_key, swboard->session_id);
 	}
 	else
 	{
-		msn_cmdproc_send(cmdproc, "USR", "%s %s",
-						 purple_account_get_username(account),
-						 swboard->auth_key);
+		trans = msn_transaction_new(cmdproc, "USR", "%s %s",
+									purple_account_get_username(account),
+									swboard->auth_key);
 	}
+
+	msn_transaction_set_error_cb(trans, ans_usr_error);
+	msn_transaction_set_data(trans, swboard);
+	msn_cmdproc_send_trans(cmdproc, trans);
+}
+
+static void
+ans_usr_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
+{
+	MsnSwitchBoard *swboard;
+	char **params;
+	char *passport;
+	int reason = MSN_SB_ERROR_UNKNOWN;
+
+	if (error == 911)
+	{
+		reason = MSN_SB_ERROR_AUTHFAILED;
+	}
+
+	purple_debug_warning("msn", "ans_usr_error: command %s gave error %i\n", trans->command, error);
+
+	params = g_strsplit(trans->params, " ", 0);
+	passport = params[0];
+	swboard = trans->data;
+
+	swboard_error_helper(swboard, reason, passport);
+
+	g_strfreev(params);
 }
 
 static void
--- a/libpurple/protocols/msn/switchboard.h	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/msn/switchboard.h	Mon Jun 18 01:48:35 2007 +0000
@@ -46,6 +46,7 @@
 	MSN_SB_ERROR_USER_OFFLINE, /**< The user to call is offline. */
 	MSN_SB_ERROR_CONNECTION, /**< There was a connection error. */
 	MSN_SB_ERROR_TOO_FAST, /**< We are sending too fast */
+	MSN_SB_ERROR_AUTHFAILED, /**< Authentication failed joining the switchboard session */
 	MSN_SB_ERROR_UNKNOWN /**< An unknown error occurred. */
 
 } MsnSBErrorType;
--- a/libpurple/protocols/msn/sync.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/msn/sync.c	Mon Jun 18 01:48:35 2007 +0000
@@ -99,8 +99,19 @@
 
 	/* HACK */
 	if (group_id == 0)
+	{
 		/* Group of ungroupped buddies */
+		if (session->sync->total_users == 0)
+		{
+			cmdproc->cbs_table = session->sync->old_cbs_table;
+
+			msn_session_finish_login(session);
+
+			msn_sync_destroy(session->sync);
+			session->sync = NULL;
+		}
 		return;
+	}
 
 	if ((purple_find_group(name)) == NULL)
 	{
@@ -184,6 +195,8 @@
 
 	user = sync->last_user;
 
+	g_return_if_fail(user != NULL);
+
 	type     = cmd->params[0];
 	value    = cmd->params[1];
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/null/Makefile.am	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,21 @@
+EXTRA_DIST = README Makefile.mingw
+
+pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
+
+NULLSOURCES = nullprpl.c
+
+AM_CFLAGS = $(st)
+
+libnull_la_LDFLAGS = -module -avoid-version
+
+# nullprpl isn't built by default. when it is built, it's dynamically linked.
+st =
+pkg_LTLIBRARIES   = libnull.la
+libnull_la_SOURCES = $(NULLSOURCES)
+libnull_la_LIBADD  = $(GLIB_LIBS)
+
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/libpurple \
+	-I$(top_builddir)/libpurple \
+	$(GLIB_CFLAGS) \
+	$(DEBUG_CFLAGS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/null/Makefile.mingw	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,77 @@
+#
+# Makefile.mingw
+#
+# Description: Makefile for win32 (mingw) version of libnull
+#
+
+PIDGIN_TREE_TOP := ../../..
+include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+
+TARGET = libnull
+TYPE = PLUGIN
+
+# Static or Plugin...
+ifeq ($(TYPE),STATIC)
+  DEFINES += -DSTATIC
+  DLL_INSTALL_DIR =	$(PURPLE_INSTALL_DIR)
+else
+ifeq ($(TYPE),PLUGIN)
+  DLL_INSTALL_DIR =	$(PURPLE_INSTALL_PLUGINS_DIR)
+endif
+endif
+
+##
+## INCLUDE PATHS
+##
+INCLUDE_PATHS +=	-I. \
+			-I$(GTK_TOP)/include \
+			-I$(GTK_TOP)/include/glib-2.0 \
+			-I$(GTK_TOP)/lib/glib-2.0/include \
+			-I$(PURPLE_TOP) \
+			-I$(PURPLE_TOP)/win32 \
+			-I$(PIDGIN_TREE_TOP)
+
+LIB_PATHS +=		-L$(GTK_TOP)/lib \
+			-L$(PURPLE_TOP)
+
+##
+##  SOURCES, OBJECTS
+##
+C_SRC =	nullprpl.c
+
+OBJECTS = $(C_SRC:%.c=%.o)
+
+##
+## LIBRARIES
+##
+LIBS =	\
+			-lglib-2.0 \
+			-lintl \
+			-lws2_32 \
+			-lpurple
+
+include $(PIDGIN_COMMON_RULES)
+
+##
+## TARGET DEFINITIONS
+##
+.PHONY: all install clean
+
+all: $(TARGET).dll
+
+install: all $(DLL_INSTALL_DIR) $(PURPLE_INSTALL_DIR)
+	cp $(TARGET).dll $(DLL_INSTALL_DIR)
+
+$(OBJECTS): $(PURPLE_CONFIG_H)
+
+$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
+	$(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
+
+##
+## CLEAN RULES
+##
+clean:
+	rm -f $(OBJECTS)
+	rm -f $(TARGET).dll
+
+include $(PIDGIN_COMMON_TARGETS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/null/README	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,46 @@
+nullprpl
+
+--------
+OVERVIEW
+--------
+Nullprpl is a mock protocol plugin for Pidgin and libpurple. You can create
+accounts with it, sign on and off, add buddies, and send and receive IMs, all
+without connecting to a server!
+
+Beyond that basic functionality, nullprpl supports presence and away/available
+messages, offline messages, user info, typing notification, privacy
+allow/block lists, chat rooms, whispering, room lists, and protocol icons and
+emblems. Notable missing features are file transfer and account registration
+and authentication.
+
+Nullprpl is intended as an example of how to write a libpurple protocol
+plugin. It doesn't contain networking code or an event loop, but it does
+demonstrate how to use the libpurple API to do pretty much everything a prpl
+might need to do.
+
+Nullprpl is also a useful tool for hacking on Pidgin, Finch, and other
+libpurple clients. It's a full-featured protocol plugin, but doesn't depend on
+an external server, so it's a quick and easy way to exercise test new code. It
+also allows you to work while you're disconnected.
+
+-----------------------
+BUILDING AND INSTALLING
+-----------------------
+
+To build, just run ./configure as usual in the root directory of the pidgin
+source distribution. Then cd libpurple/protocols/null and type make. To
+install, copy libnull.la and .libs/libnull.so into your ~/.purple/plugins
+directory. Then run Pidgin.
+
+To build nullprpl on Windows (with Cygwin/MinGW), use Makefile.mingw.
+
+-----
+USAGE
+-----
+To add a nullprpl account, go to the account editor window and click Add.
+Select Nullprpl from the protocol drop-down list, and enter any username you
+want.
+
+Now, use Pidgin like normal. You can add buddies, send IMs, set away messages,
+etc. If you send IMs to your own username, they will be echoed back to you.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/null/nullprpl.c	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,1202 @@
+/**
+ * purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * Nullprpl is a mock protocol plugin for Pidgin and libpurple. You can create
+ * accounts with it, sign on and off, add buddies, and send and receive IMs,
+ * all without connecting to a server!
+ * 
+ * Beyond that basic functionality, nullprpl supports presence and
+ * away/available messages, offline messages, user info, typing notification,
+ * privacy allow/block lists, chat rooms, whispering, room lists, and protocol
+ * icons and emblems. Notable missing features are file transfer and account
+ * registration and authentication.
+ * 
+ * Nullprpl is intended as an example of how to write a libpurple protocol
+ * plugin. It doesn't contain networking code or an event loop, but it does
+ * demonstrate how to use the libpurple API to do pretty much everything a prpl
+ * might need to do.
+ * 
+ * Nullprpl is also a useful tool for hacking on Pidgin, Finch, and other
+ * libpurple clients. It's a full-featured protocol plugin, but doesn't depend
+ * on an external server, so it's a quick and easy way to exercise test new
+ * code. It also allows you to work while you're disconnected.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+
+#include <glib.h>
+
+#include "internal.h"
+#include "config.h"
+#include "account.h"
+#include "accountopt.h"
+#include "blist.h"
+#include "cmds.h"
+#include "conversation.h"
+#include "connection.h"
+#include "debug.h"
+#include "notify.h"
+#include "privacy.h"
+#include "prpl.h"
+#include "roomlist.h"
+#include "status.h"
+#include "util.h"
+#include "version.h"
+
+
+#define NULLPRPL_ID "prpl-null"
+static PurplePlugin *_null_protocol = NULL;
+
+#define NULL_STATUS_ONLINE   "online"
+#define NULL_STATUS_AWAY     "away"
+#define NULL_STATUS_OFFLINE  "offline"
+
+typedef void (*GcFunc)(PurpleConnection *from,
+                       PurpleConnection *to,
+                       gpointer userdata);
+
+typedef struct {
+  GcFunc fn;
+  PurpleConnection *from;
+  gpointer userdata;
+} GcFuncData;
+
+/*
+ * stores offline messages that haven't been delivered yet. maps username
+ * (char *) to GList * of GOfflineMessages. initialized in nullprpl_init.
+ */
+GHashTable* goffline_messages = NULL;
+
+typedef struct {
+  char *from;
+  char *message;
+  time_t mtime;
+  PurpleMessageFlags flags;
+} GOfflineMessage;
+
+/*
+ * helpers
+ */
+static PurpleConnection *get_nullprpl_gc(const char *username) {
+  PurpleAccount *acct = purple_accounts_find(username, NULLPRPL_ID);
+  if (acct && purple_account_is_connected(acct))
+    return acct->gc;
+  else
+    return NULL;
+}
+
+static void call_if_nullprpl(gpointer data, gpointer userdata) {
+  PurpleConnection *gc = (PurpleConnection *)(data);
+  GcFuncData *gcfdata = (GcFuncData *)userdata;
+
+  if (!strcmp(gc->account->protocol_id, NULLPRPL_ID))
+    gcfdata->fn(gcfdata->from, gc, gcfdata->userdata);
+}
+
+static void foreach_nullprpl_gc(GcFunc fn, PurpleConnection *from,
+                                gpointer userdata) {
+  GcFuncData gcfdata = { fn, from, userdata };
+  g_list_foreach(purple_connections_get_all(), call_if_nullprpl,
+                 &gcfdata);
+}
+
+
+typedef void(*ChatFunc)(PurpleConvChat *from, PurpleConvChat *to,
+                        int id, const char *room, gpointer userdata);
+
+typedef struct {
+  ChatFunc fn;
+  PurpleConvChat *from_chat;
+  gpointer userdata;
+} ChatFuncData;
+
+static void call_chat_func(gpointer data, gpointer userdata) {
+  PurpleConnection *to = (PurpleConnection *)data;
+  ChatFuncData *cfdata = (ChatFuncData *)userdata;
+
+  int id = cfdata->from_chat->id;
+  PurpleConversation *conv = purple_find_chat(to, id);
+  if (conv) {
+    PurpleConvChat *chat = purple_conversation_get_chat_data(conv);
+    cfdata->fn(cfdata->from_chat, chat, id, conv->name, cfdata->userdata);
+  }
+}
+
+static void foreach_gc_in_chat(ChatFunc fn, PurpleConnection *from,
+                               int id, gpointer userdata) {
+  PurpleConversation *conv = purple_find_chat(from, id);
+  ChatFuncData cfdata = { fn,
+                          purple_conversation_get_chat_data(conv),
+                          userdata };
+
+  g_list_foreach(purple_connections_get_all(), call_chat_func,
+                 &cfdata);
+}
+
+
+static void discover_status(PurpleConnection *from, PurpleConnection *to,
+                            gpointer userdata) {
+  char *from_username = from->account->username;
+  char *to_username = to->account->username;
+
+  if (purple_find_buddy(from->account, to_username)) {
+    PurpleStatus *status = purple_account_get_active_status(to->account);
+    const char *status_id = purple_status_get_id(status);
+    const char *message = purple_status_get_attr_string(status, "message");
+
+    if (!strcmp(status_id, NULL_STATUS_ONLINE) ||
+        !strcmp(status_id, NULL_STATUS_AWAY) ||
+        !strcmp(status_id, NULL_STATUS_OFFLINE)) {
+      purple_debug_info("nullprpl", "%s sees that %s is %s: %s\n",
+                        from_username, to_username, status_id, message);
+      purple_prpl_got_user_status(from->account, to_username, status_id,
+                                  (message) ? "message" : NULL, message, NULL);
+    } else {
+      purple_debug_error("nullprpl",
+                         "%s's buddy %s has an unknown status: %s, %s",
+                         from_username, to_username, status_id, message);
+    }
+  }
+}
+
+static void report_status_change(PurpleConnection *from, PurpleConnection *to,
+                                 gpointer userdata) {
+  purple_debug_info("nullprpl", "notifying %s that %s changed status\n",
+                    to->account->username, from->account->username);
+  discover_status(to, from, NULL);
+}
+
+
+/* 
+ * UI callbacks
+ */
+static void nullprpl_input_user_info(PurplePluginAction *action)
+{
+  PurpleConnection *gc = (PurpleConnection *)action->context;
+  PurpleAccount *acct = purple_connection_get_account(gc);
+  purple_debug_info("nullprpl", "showing 'Set User Info' dialog for %s\n",
+                    acct->username);
+
+  purple_account_request_change_user_info(acct);
+}
+
+/* this is set to the actions member of the PurplePluginInfo struct at the
+ * bottom.
+ */
+static GList *nullprpl_actions(PurplePlugin *plugin, gpointer context)
+{
+  PurplePluginAction *action = purple_plugin_action_new(
+    _("Set User Info..."), nullprpl_input_user_info);
+  return g_list_append(NULL, action);
+}
+
+
+/*
+ * prpl functions
+ */
+static const char *nullprpl_list_icon(PurpleAccount *acct, PurpleBuddy *buddy)
+{
+  /* shamelessly steal (er, borrow) the meanwhile protocol icon. it's cute! */
+  return "meanwhile";
+}
+
+static const char *nullprpl_list_emblem(PurpleBuddy *buddy)
+{
+  const char* emblem;
+
+  if (get_nullprpl_gc(buddy->name)) {
+    PurplePresence *presence = purple_buddy_get_presence(buddy);
+    PurpleStatus *status = purple_presence_get_active_status(presence);
+    emblem = purple_status_get_name(status);
+  } else {
+    emblem = "offline";
+  }
+
+  purple_debug_info("nullprpl", "using emblem %s for %s's buddy %s\n",
+                    emblem, buddy->account->username, buddy->name);
+  return emblem;
+}
+
+static char *nullprpl_status_text(PurpleBuddy *buddy) {
+  purple_debug_info("nullprpl", "getting %s's status text for %s\n",
+                    buddy->name, buddy->account->username);
+
+  if (purple_find_buddy(buddy->account, buddy->name)) {
+    PurplePresence *presence = purple_buddy_get_presence(buddy);
+    PurpleStatus *status = purple_presence_get_active_status(presence);
+    const char *name = purple_status_get_name(status);
+    const char *message = purple_status_get_attr_string(status, "message");
+
+    char *text;
+    if (message && strlen(message) > 0)
+      text = g_strdup_printf("%s: %s", name, message);
+    else
+      text = g_strdup(name);
+
+    purple_debug_info("nullprpl", "%s's status text is %s\n", buddy->name, text);
+    return text;
+
+  } else {
+    purple_debug_info("nullprpl", "...but %s is not logged in\n", buddy->name);
+    return "Not logged in";
+  }
+}
+
+static void nullprpl_tooltip_text(PurpleBuddy *buddy,
+                                  PurpleNotifyUserInfo *info,
+                                  gboolean full) {
+  PurpleConnection *gc = get_nullprpl_gc(buddy->name);
+
+  if (gc) {
+    /* they're logged in */
+    PurplePresence *presence = purple_buddy_get_presence(buddy);
+    PurpleStatus *status = purple_presence_get_active_status(presence);
+    const char *msg = nullprpl_status_text(buddy);
+    purple_notify_user_info_add_pair(info, purple_status_get_name(status),
+                                     msg);
+
+    if (full) {
+      const char *user_info = purple_account_get_user_info(gc->account);
+      if (user_info)
+        purple_notify_user_info_add_pair(info, _("User info"), user_info);
+    }
+
+  } else {
+    /* they're not logged in */
+    purple_notify_user_info_add_pair(info, _("User info"), _("not logged in"));
+  }
+    
+  purple_debug_info("nullprpl", "showing %s tooltip for %s\n",
+                    (full) ? "full" : "short", buddy->name);
+}
+
+static GList *nullprpl_status_types(PurpleAccount *acct)
+{
+  GList *types = NULL;
+  PurpleStatusType *type;
+
+  purple_debug_info("nullprpl", "returning status types for %s: %s, %s, %s\n",
+                    acct->username,
+                    NULL_STATUS_ONLINE, NULL_STATUS_AWAY, NULL_STATUS_OFFLINE);
+
+  type = purple_status_type_new(PURPLE_STATUS_AVAILABLE, NULL_STATUS_ONLINE,
+                                NULL_STATUS_ONLINE, TRUE);
+  purple_status_type_add_attr(type, "message", _("Online"),
+                              purple_value_new(PURPLE_TYPE_STRING));
+  types = g_list_append(types, type);
+
+  type = purple_status_type_new(PURPLE_STATUS_AWAY, NULL_STATUS_AWAY,
+                                NULL_STATUS_AWAY, TRUE);
+  purple_status_type_add_attr(type, "message", _("Away"),
+                              purple_value_new(PURPLE_TYPE_STRING));
+  types = g_list_append(types, type);
+  
+  type = purple_status_type_new(PURPLE_STATUS_OFFLINE, NULL_STATUS_OFFLINE,
+                                NULL_STATUS_OFFLINE, TRUE);
+  purple_status_type_add_attr(type, "message", _("Offline"),
+                              purple_value_new(PURPLE_TYPE_STRING));
+  types = g_list_append(types, type);
+
+  return types;
+}
+
+static void blist_example_menu_item(PurpleBlistNode *node, gpointer userdata) {
+  purple_debug_info("nullprpl", "example menu item clicked on user",
+                    ((PurpleBuddy *)node)->name);
+
+  purple_notify_info(NULL,  /* plugin handle or PurpleConnection */
+                     _("Primary title"),
+                     _("Secondary title"),
+                     _("This is the callback for the nullprpl menu item."));
+}
+
+static GList *nullprpl_blist_node_menu(PurpleBlistNode *node) {
+  purple_debug_info("nullprpl", "providing buddy list context menu item\n");
+
+  if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
+    PurpleMenuAction *action = purple_menu_action_new(
+      _("Nullprpl example menu item"),
+      PURPLE_CALLBACK(blist_example_menu_item),
+      NULL,   /* userdata passed to the callback */
+      NULL);  /* child menu items */
+    return g_list_append(NULL, action);
+  } else {
+    return NULL;
+  }
+}
+
+static GList *nullprpl_chat_info(PurpleConnection *gc) {
+  struct proto_chat_entry *pce; /* defined in prpl.h */
+
+  purple_debug_info("nullprpl", "returning chat setting 'room'\n");
+
+  pce = g_new0(struct proto_chat_entry, 1);
+  pce->label = _(_("Chat _room"));
+  pce->identifier = "room";
+  pce->required = TRUE;
+
+  return g_list_append(NULL, pce);
+}
+
+static GHashTable *nullprpl_chat_info_defaults(PurpleConnection *gc,
+                                               const char *room) {
+  GHashTable *defaults;
+
+  purple_debug_info("nullprpl", "returning chat default setting "
+                    "'room' = 'default'\n");
+
+  defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
+  g_hash_table_insert(defaults, "room", g_strdup("default"));
+  return defaults;
+}  
+
+static void nullprpl_login(PurpleAccount *acct)
+{
+  PurpleConnection *gc = purple_account_get_connection(acct);
+  GList *offline_messages;
+
+  purple_debug_info("nullprpl", "logging in %s\n", acct->username);
+
+  purple_connection_update_progress(gc, _("Connecting"),
+                                    0,   /* which connection step this is */
+                                    2);  /* total number of steps */
+
+  purple_connection_update_progress(gc, _("Connected"),
+                                    1,   /* which connection step this is */
+                                    2);  /* total number of steps */
+  purple_connection_set_state(gc, PURPLE_CONNECTED);
+
+  /* tell purple about everyone on our buddy list who's connected */
+  foreach_nullprpl_gc(discover_status, gc, NULL);
+
+  /* notify other nullprpl accounts */
+  foreach_nullprpl_gc(report_status_change, gc, NULL);
+
+  /* fetch stored offline messages */
+  purple_debug_info("nullprpl", "checking for offline messages for %s\n",
+                    acct->username);
+  offline_messages = g_hash_table_lookup(goffline_messages, acct->username); 
+  while (offline_messages) {
+    GOfflineMessage *message = (GOfflineMessage *)offline_messages->data;
+    purple_debug_info("nullprpl", "delivering offline message to %s: %s\n",
+                      acct->username, message->message);
+    serv_got_im(gc, message->from, message->message, message->flags,
+                message->mtime);
+    offline_messages = g_list_next(offline_messages);
+
+    g_free(message->from);
+    g_free(message->message);
+    g_free(message);
+  }
+
+  g_list_free(offline_messages);
+  g_hash_table_remove(goffline_messages, &acct->username);
+}
+
+static void nullprpl_close(PurpleConnection *gc)
+{
+  /* notify other nullprpl accounts */
+  foreach_nullprpl_gc(report_status_change, gc, NULL);
+}
+
+static int nullprpl_send_im(PurpleConnection *gc, const char *who,
+                            const char *message, PurpleMessageFlags flags)
+{
+  const char *from_username = gc->account->username;
+  PurpleMessageFlags receive_flags = ((flags & ~PURPLE_MESSAGE_SEND)
+                                      | PURPLE_MESSAGE_RECV);
+  PurpleAccount *to_acct = purple_accounts_find(who, NULLPRPL_ID);
+  PurpleConnection *to;
+
+  purple_debug_info("nullprpl", "sending message from %s to %s: %s\n",
+                    from_username, who, message);
+
+  /* is the sender blocked by the recipient's privacy settings? */
+  if (to_acct && !purple_privacy_check(to_acct, gc->account->username)) {
+    char *msg = g_strdup_printf(
+      _("Your message was blocked by %s's privacy settings."), who);
+    purple_debug_info("nullprpl",
+                      "discarding; %s is blocked by %s's privacy settings\n",
+                      from_username, who);
+    purple_conv_present_error(who, gc->account, msg);
+    g_free(msg);
+    return 0;
+  }
+
+  /* is the recipient online? */
+  to = get_nullprpl_gc(who);
+  if (to) {  /* yes, send */
+    serv_got_im(to, from_username, message, receive_flags, time(NULL));
+
+  } else {  /* nope, store as an offline message */
+    GOfflineMessage *offline_message;
+    GList *messages;
+
+    purple_debug_info("nullprpl",
+                      "%s is offline, sending as offline message\n", who);
+    offline_message = g_new0(GOfflineMessage, 1);
+    offline_message->from = g_strdup(from_username);
+    offline_message->message = g_strdup(message);
+    offline_message->mtime = time(NULL);
+    offline_message->flags = receive_flags;
+
+    messages = g_hash_table_lookup(goffline_messages, who);
+    messages = g_list_append(messages, offline_message);
+    g_hash_table_insert(goffline_messages, g_strdup(who), messages);
+  }
+
+   return 1;
+}
+
+static void nullprpl_set_info(PurpleConnection *gc, const char *info) {
+  purple_debug_info("nullprpl", "setting %s's user info to %s\n",
+                    gc->account->username, info);
+}
+
+static char *typing_state_to_string(PurpleTypingState typing) {
+  switch (typing) {
+  case PURPLE_NOT_TYPING:  return "is not typing";
+  case PURPLE_TYPING:      return "is typing";
+  case PURPLE_TYPED:       return "stopped typing momentarily";
+  default:               return "unknown typing state";
+  }
+}
+
+static void notify_typing(PurpleConnection *from, PurpleConnection *to,
+                          gpointer typing) {
+  char *from_username = from->account->username;
+  char *action = typing_state_to_string((PurpleTypingState)typing);
+  purple_debug_info("nullprpl", "notifying %s that %s %s\n",
+                    to->account->username, from_username, action);
+
+  serv_got_typing(to,
+                  from_username,
+                  0, /* if non-zero, a timeout in seconds after which to
+                      * reset the typing status to PURPLE_NOT_TYPING */
+                  (PurpleTypingState)typing);
+}
+
+static unsigned int nullprpl_send_typing(PurpleConnection *gc, const char *name,
+                                         PurpleTypingState typing) {
+  purple_debug_info("nullprpl", "%s %s\n", gc->account->username,
+                    typing_state_to_string(typing));
+  foreach_nullprpl_gc(notify_typing, gc, (gpointer)typing);
+  return 0;
+}
+
+static void nullprpl_get_info(PurpleConnection *gc, const char *username) {
+  const char *body;
+  PurpleNotifyUserInfo *info = purple_notify_user_info_new();
+  PurpleAccount *acct;
+
+  purple_debug_info("nullprpl", "Fetching %s's user info for %s\n", username,
+                    gc->account->username);
+
+  if (!get_nullprpl_gc(username)) {
+    char *msg = g_strdup_printf(_("%s is not logged in."), username);
+    purple_notify_error(gc, _("User Info"), _("User info not available. "), msg);
+    g_free(msg);
+  }
+
+  acct = purple_accounts_find(username, NULLPRPL_ID);
+  if (acct)
+    body = purple_account_get_user_info(acct);
+  else
+    body = _("No user info.");
+  purple_notify_user_info_add_pair(info, "Info", body);
+
+  /* show a buddy's user info in a nice dialog box */
+  purple_notify_userinfo(gc,        /* connection the buddy info came through */
+                         username,  /* buddy's username */
+                         info,      /* body */
+                         NULL,      /* callback called when dialog closed */
+                         NULL);     /* userdata for callback */
+}
+
+static void nullprpl_set_status(PurpleAccount *acct, PurpleStatus *status) {
+  const char *msg = purple_status_get_attr_string(status, "message");
+  purple_debug_info("nullprpl", "setting %s's status to %s: %s\n",
+                    acct->username, purple_status_get_name(status), msg);
+
+  foreach_nullprpl_gc(report_status_change, get_nullprpl_gc(acct->username),
+                      NULL);
+}
+
+static void nullprpl_set_idle(PurpleConnection *gc, int idletime) {
+  purple_debug_info("nullprpl",
+                    "purple reports that %s has been idle for %d seconds\n",
+                    gc->account->username, idletime);
+}
+
+static void nullprpl_change_passwd(PurpleConnection *gc, const char *old_pass,
+                                   const char *new_pass) {
+  purple_debug_info("nullprpl", "%s wants to change their password\n",
+                    gc->account->username);
+}
+
+static void nullprpl_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
+                               PurpleGroup *group)
+{
+  char *username = gc->account->username;
+  PurpleConnection *buddy_gc = get_nullprpl_gc(buddy->name);
+
+  purple_debug_info("nullprpl", "adding %s to %s's buddy list\n", buddy->name,
+                    username);
+
+  if (buddy_gc) {
+    PurpleAccount *buddy_acct = buddy_gc->account;
+
+    discover_status(gc, buddy_gc, NULL);
+
+    if (purple_find_buddy(buddy_acct, username)) {
+      purple_debug_info("nullprpl", "%s is already on %s's buddy list\n",
+                        username, buddy->name);
+    } else {
+      purple_debug_info("nullprpl", "asking %s if they want to add %s\n",
+                        buddy->name, username);
+      purple_account_request_add(buddy_acct,
+                                 username,
+                                 NULL,   /* local account id (rarely used) */
+                                 NULL,   /* alias */
+                                 NULL);  /* message */
+    }
+  }
+}
+
+static void nullprpl_add_buddies(PurpleConnection *gc, GList *buddies,
+                                 GList *groups) {
+  GList *buddy = buddies;
+  GList *group = groups;
+
+  purple_debug_info("nullprpl", "adding multiple buddies\n");
+
+  while (buddy && group) {
+    nullprpl_add_buddy(gc, (PurpleBuddy *)buddy->data, (PurpleGroup *)group->data);
+    buddy = g_list_next(buddy);
+    group = g_list_next(group);
+  }
+}
+
+static void nullprpl_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
+                                  PurpleGroup *group)
+{
+  purple_debug_info("nullprpl", "removing %s from %s's buddy list\n",
+                    buddy->name, gc->account->username);
+}
+
+static void nullprpl_remove_buddies(PurpleConnection *gc, GList *buddies,
+                                    GList *groups) {
+  GList *buddy = buddies;
+  GList *group = groups;
+
+  purple_debug_info("nullprpl", "removing multiple buddies\n");
+
+  while (buddy && group) {
+    nullprpl_remove_buddy(gc, (PurpleBuddy *)buddy->data,
+                          (PurpleGroup *)group->data);
+    buddy = g_list_next(buddy);
+    group = g_list_next(group);
+  }
+}
+
+/*
+ * nullprpl uses purple's local whitelist and blacklist, stored in blist.xml, as
+ * its authoritative privacy settings, and uses purple's logic (specifically
+ * purple_privacy_check(), from privacy.h), to determine whether messages are
+ * allowed or blocked.
+ */
+static void nullprpl_add_permit(PurpleConnection *gc, const char *name) {
+  purple_debug_info("nullprpl", "%s adds %s to their allowed list\n",
+                    gc->account->username, name);
+}
+
+static void nullprpl_add_deny(PurpleConnection *gc, const char *name) {
+  purple_debug_info("nullprpl", "%s adds %s to their blocked list\n",
+                    gc->account->username, name);
+}
+
+static void nullprpl_rem_permit(PurpleConnection *gc, const char *name) {
+  purple_debug_info("nullprpl", "%s removes %s from their allowed list\n",
+                    gc->account->username, name);
+}
+
+static void nullprpl_rem_deny(PurpleConnection *gc, const char *name) {
+  purple_debug_info("nullprpl", "%s removes %s from their blocked list\n",
+                    gc->account->username, name);
+}
+
+static void nullprpl_set_permit_deny(PurpleConnection *gc) {
+  /* this is for synchronizing the local black/whitelist with the server.
+   * for nullprpl, it's a noop.
+   */
+}
+
+static void joined_chat(PurpleConvChat *from, PurpleConvChat *to,
+                        int id, const char *room, gpointer userdata) {
+  /*  tell their chat window that we joined */
+  purple_debug_info("nullprpl", "%s sees that %s joined chat room %s\n",
+                    to->nick, from->nick, room);
+  purple_conv_chat_add_user(to,
+                            from->nick,
+                            NULL,   /* user-provided join message, IRC style */
+                            PURPLE_CBFLAGS_NONE,
+                            TRUE);  /* show a join message */
+
+  if (from != to) {
+    /* add them to our chat window */
+    purple_debug_info("nullprpl", "%s sees that %s is in chat room %s\n",
+                      from->nick, to->nick, room);
+    purple_conv_chat_add_user(from,
+                              to->nick,
+                              NULL,   /* user-provided join message, IRC style */
+                              PURPLE_CBFLAGS_NONE,
+                              FALSE);  /* show a join message */
+  }
+}
+
+static void nullprpl_join_chat(PurpleConnection *gc, GHashTable *components) {
+  char *username = gc->account->username;
+  char *room = g_hash_table_lookup(components, "room");
+  int chat_id = g_str_hash(room);
+  purple_debug_info("nullprpl", "%s is joining chat room %s\n", username, room);
+
+  if (!purple_find_chat(gc, chat_id)) {
+    serv_got_joined_chat(gc, chat_id, room);
+
+    /* tell everyone that we joined, and add them if they're already there */
+    foreach_gc_in_chat(joined_chat, gc, chat_id, NULL);
+  } else {
+    purple_debug_info("nullprpl", "%s is already in chat room %s\n", username,
+                      room);
+    purple_notify_info(gc,
+                       _("Join chat"),
+                       _("Join chat"),
+                       g_strdup_printf("%s is already in chat room %s.",
+                                       username, room));
+  }
+}
+
+static void nullprpl_reject_chat(PurpleConnection *gc, GHashTable *components) {
+  char *invited_by = g_hash_table_lookup(components, "invited_by");
+  char *room = g_hash_table_lookup(components, "room");
+  char *username = gc->account->username;
+  PurpleConnection *invited_by_gc = get_nullprpl_gc(invited_by);
+  char *message = g_strdup_printf(
+    "%s %s %s.",
+    username,
+    _("has rejected your invitation to join the chat room"),
+    room);
+
+  purple_debug_info("nullprpl",
+                    "%s has rejected %s's invitation to join chat room %s\n",
+                    username, invited_by, room);
+
+  purple_notify_info(invited_by_gc,
+                     _("Chat invitation rejected"),
+                     _("Chat invitation rejected"),
+                     message);
+}
+
+static char *nullprpl_get_chat_name(GHashTable *components) {
+  char *room = g_hash_table_lookup(components, "room");
+  purple_debug_info("nullprpl", "reporting chat room name '%s'\n", room);
+  return room;
+}
+
+static void nullprpl_chat_invite(PurpleConnection *gc, int id,
+                                 const char *message, const char *who) {
+  char *username = gc->account->username;
+  PurpleConversation *conv = purple_find_chat(gc, id);
+  char *room = conv->name;
+  PurpleAccount *to_acct = purple_accounts_find(who, NULLPRPL_ID);
+
+  purple_debug_info("nullprpl", "%s is inviting %s to join chat room %s\n",
+                    username, who, room);
+
+  if (to_acct) {
+    PurpleConversation *to_conv = purple_find_chat(to_acct->gc, id);
+    if (to_conv) {
+      purple_debug_info("nullprpl",
+                        "%s is already in chat room %s; "
+                        "ignoring invitation from %s\n",
+                        who, room, username);
+      purple_notify_info(gc,
+                         _("Chat invitation"),
+                         _("Chat invitation"),
+                         g_strdup_printf("%s is already in chat room %s.",
+                                         who, room));
+    } else {
+      GHashTable *components;
+      components = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, free);
+      g_hash_table_replace(components, "room", g_strdup(room));
+      g_hash_table_replace(components, "invited_by", g_strdup(username));
+      serv_got_chat_invite(to_acct->gc, room, username, message, components);
+    }
+  }
+}
+
+static void left_chat_room(PurpleConvChat *from, PurpleConvChat *to,
+                           int id, const char *room, gpointer userdata) {
+  if (from != to) {
+    /*  tell their chat window that we left */
+    purple_debug_info("nullprpl", "%s sees that %s left chat room %s\n",
+                      to->nick, from->nick, room);
+    purple_conv_chat_remove_user(to,
+                                 from->nick,
+                                 NULL);  /* user-provided message, IRC style */
+  }
+}
+
+static void nullprpl_chat_leave(PurpleConnection *gc, int id) {
+  PurpleConversation *conv = purple_find_chat(gc, id);
+  purple_debug_info("nullprpl", "%s is leaving chat room %s\n",
+                    gc->account->username, conv->name);
+
+  /* tell everyone that we left */
+  foreach_gc_in_chat(left_chat_room, gc, id, NULL);
+}
+
+static PurpleCmdRet send_whisper(PurpleConversation *conv, const gchar *cmd,
+                                 gchar **args, gchar **error, void *userdata) {
+  const char *to_username;
+  const char *message;
+  const char *from_username;
+  PurpleConvChat *chat;
+  PurpleConvChatBuddy *chat_buddy;
+  PurpleConnection *to;
+
+  /* parse args */
+  to_username = args[0];
+  message = args[1];
+
+  if (!to_username || strlen(to_username) == 0) {
+    *error = g_strdup(_("Whisper is missing recipient."));
+    return PURPLE_CMD_RET_FAILED;
+  } else if (!message || strlen(message) == 0) {
+    *error = g_strdup(_("Whisper is missing message."));
+    return PURPLE_CMD_RET_FAILED;
+  }
+
+  from_username = conv->account->username;
+  purple_debug_info("nullprpl", "%s whispers to %s in chat room %s: %s\n",
+                    from_username, to_username, conv->name, message);
+
+  chat = purple_conversation_get_chat_data(conv);
+  chat_buddy = purple_conv_chat_cb_find(chat, to_username);
+  to = get_nullprpl_gc(to_username);
+
+  if (!chat_buddy) {
+    /* this will be freed by the caller */
+    *error = g_strdup_printf(_("%s is not logged in."), to_username);
+    return PURPLE_CMD_RET_FAILED;
+  } else if (!to) {
+    *error = g_strdup_printf(_("%s is not in this chat room."), to_username);
+    return PURPLE_CMD_RET_FAILED;
+  } else {
+    /* write the whisper in the sender's chat window  */
+    char *message_to = g_strdup_printf("%s (to %s)", message, to_username);
+    purple_conv_chat_write(chat, from_username, message_to,
+                           PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_WHISPER,
+                           time(NULL));
+    g_free(message_to);
+
+    /* send the whisper */
+    serv_chat_whisper(to, chat->id, from_username, message);
+
+    return PURPLE_CMD_RET_OK;
+  }
+}
+
+static void nullprpl_chat_whisper(PurpleConnection *gc, int id, const char *who,
+                                  const char *message) {
+  char *username = gc->account->username;
+  PurpleConversation *conv = purple_find_chat(gc, id);
+  purple_debug_info("nullprpl",
+                    "%s receives whisper from %s in chat room %s: %s\n",
+                    username, who, conv->name, message);
+
+  /* receive whisper on recipient's account */
+  serv_got_chat_in(gc, id, who, PURPLE_MESSAGE_RECV | PURPLE_MESSAGE_WHISPER,
+                   message, time(NULL));
+}
+
+static void receive_chat_message(PurpleConvChat *from, PurpleConvChat *to,
+                                 int id, const char *room, gpointer userdata) {
+  const char *message = (const char *)userdata;
+  PurpleConnection *to_gc = get_nullprpl_gc(to->nick);
+
+  purple_debug_info("nullprpl",
+                    "%s receives message from %s in chat room %s: %s\n",
+                    to->nick, from->nick, room, message);
+  serv_got_chat_in(to_gc, id, from->nick, PURPLE_MESSAGE_RECV, message,
+                   time(NULL));
+}
+
+static int nullprpl_chat_send(PurpleConnection *gc, int id, const char *message,
+                              PurpleMessageFlags flags) {
+  char *username = gc->account->username;
+  PurpleConversation *conv = purple_find_chat(gc, id);
+
+  if (conv) {
+    purple_debug_info("nullprpl",
+                      "%s is sending message to chat room %s: %s\n", username,
+                      conv->name, message);
+
+    /* send message to everyone in the chat room */
+    foreach_gc_in_chat(receive_chat_message, gc, id, (gpointer)message);
+    return 0;
+  } else {
+    purple_debug_info("nullprpl",
+                      "tried to send message from %s to chat room #%d: %s\n"
+                      "but couldn't find chat room",
+                      username, id, message);
+    return -1;
+  }
+}
+
+static void nullprpl_register_user(PurpleAccount *acct) {
+ purple_debug_info("nullprpl", "registering account for %s\n",
+                   acct->username);
+}
+
+static void nullprpl_get_cb_info(PurpleConnection *gc, int id, const char *who) {
+  PurpleConversation *conv = purple_find_chat(gc, id);
+  purple_debug_info("nullprpl",
+                    "retrieving %s's info for %s in chat room %s\n", who,
+                    gc->account->username, conv->name);
+
+  nullprpl_get_info(gc, who);
+}
+
+static void nullprpl_alias_buddy(PurpleConnection *gc, const char *who,
+                                 const char *alias) {
+ purple_debug_info("nullprpl", "%s sets %'s alias to %s\n",
+                   gc->account->username, who, alias);
+}
+
+static void nullprpl_group_buddy(PurpleConnection *gc, const char *who,
+                                 const char *old_group,
+                                 const char *new_group) {
+  purple_debug_info("nullprpl", "%s has moved %s from group %s to group %s\n",
+                    who, old_group, new_group);
+}
+
+static void nullprpl_rename_group(PurpleConnection *gc, const char *old_name,
+                                  PurpleGroup *group, GList *moved_buddies) {
+  purple_debug_info("nullprpl", "%s has renamed group %s to %s\n",
+                    gc->account->username, old_name, group->name);
+}
+
+static void nullprpl_convo_closed(PurpleConnection *gc, const char *who) {
+  purple_debug_info("nullprpl", "%s's conversation with %s was closed\n",
+                    gc->account->username, who);
+}
+
+/* normalize a username (e.g. remove whitespace, add default domain, etc.)
+ * for nullprpl, this is a noop.
+ */
+static const char *nullprpl_normalize(const PurpleAccount *acct,
+                                      const char *input) {
+  return NULL;
+}
+
+static void nullprpl_set_buddy_icon(PurpleConnection *gc,
+                                    PurpleStoredImage *img) {
+ purple_debug_info("nullprpl", "setting %s's buddy icon to %s\n",
+                   gc->account->username, purple_imgstore_get_filename(img));
+}
+
+static void nullprpl_remove_group(PurpleConnection *gc, PurpleGroup *group) {
+  purple_debug_info("nullprpl", "%s has removed group %s\n",
+                    gc->account->username, group->name);
+}
+
+
+static void set_chat_topic_fn(PurpleConvChat *from, PurpleConvChat *to,
+                              int id, const char *room, gpointer userdata) {
+  const char *topic = (const char *)userdata;
+  const char *username = from->conv->account->username;
+  char *msg;
+
+  purple_conv_chat_set_topic(to, username, topic);
+
+  if (topic && strlen(topic) > 0)
+    msg = g_strdup_printf(_("%s sets topic to: %s"), username, topic);
+  else
+    msg = g_strdup_printf(_("%s clears topic"), username);
+
+  purple_conv_chat_write(to, username, msg,
+                         PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG,
+                         time(NULL));
+  g_free(msg);
+}
+
+static void nullprpl_set_chat_topic(PurpleConnection *gc, int id,
+                                    const char *topic) {
+  PurpleConversation *conv = purple_find_chat(gc, id);
+  PurpleConvChat *chat = purple_conversation_get_chat_data(conv);
+  const char *last_topic;
+
+  if (!chat)
+    return;
+
+  purple_debug_info("nullprpl", "%s sets topic of chat room '%s' to '%s'\n",
+                    gc->account->username, conv->name, topic);
+
+  last_topic = purple_conv_chat_get_topic(chat);
+  if ((!topic && !last_topic) ||
+      (topic && last_topic && !strcmp(topic, last_topic)))
+    return;  /* topic is unchanged, this is a noop */
+
+  foreach_gc_in_chat(set_chat_topic_fn, gc, id, (gpointer)topic);
+}
+
+static gboolean nullprpl_finish_get_roomlist(gpointer roomlist) {
+  purple_roomlist_set_in_progress((PurpleRoomlist *)roomlist, FALSE);
+  return FALSE;
+}
+
+static PurpleRoomlist *nullprpl_roomlist_get_list(PurpleConnection *gc) {
+  char *username = gc->account->username;
+  PurpleRoomlist *roomlist = purple_roomlist_new(gc->account);
+  GList *fields = NULL;
+  PurpleRoomlistField *field;
+  GList *chats;
+  GList *seen_ids = NULL;
+
+  purple_debug_info("nullprpl", "%s asks for room list; returning:\n", username);
+
+  /* set up the room list */
+  field = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "room",
+                                    "room", TRUE /* hidden */);
+  fields = g_list_append(fields, field);
+
+  field = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_INT, "Id", "Id", FALSE);
+  fields = g_list_append(fields, field);
+
+  purple_roomlist_set_fields(roomlist, fields);
+
+  /* add each chat room. the chat ids are cached in seen_ids so that each room
+   * is only returned once, even if multiple users are in it. */
+  for (chats  = purple_get_chats(); chats; chats = g_list_next(chats)) {
+    PurpleConversation *conv = (PurpleConversation *)chats->data;
+    PurpleRoomlistRoom *room;
+    char *name = conv->name;
+    int id = purple_conversation_get_chat_data(conv)->id;
+
+    /* have we already added this room? */
+    if (g_list_find_custom(seen_ids, name, (GCompareFunc)strcmp))
+      continue;                                /* yes! try the next one. */
+
+    seen_ids = g_list_append(seen_ids, name);  /* no, it's new. */
+    purple_debug_info("nullprpl", "%s (%d), ", name, id);
+
+    room = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM, name, NULL);
+    purple_roomlist_room_add_field(roomlist, room, name);
+    purple_roomlist_room_add_field(roomlist, room, &id);
+    purple_roomlist_room_add(roomlist, room);
+  }
+
+  purple_timeout_add(1 /* ms */, nullprpl_finish_get_roomlist, roomlist);
+  return roomlist;
+}
+
+static void nullprpl_roomlist_cancel(PurpleRoomlist *list) {
+ purple_debug_info("nullprpl", "%s asked to cancel room list request\n",
+                   list->account->username);
+}
+
+static void nullprpl_roomlist_expand_category(PurpleRoomlist *list,
+                                              PurpleRoomlistRoom *category) {
+ purple_debug_info("nullprpl", "%s asked to expand room list category %s\n",
+                   list->account->username, category->name);
+}
+
+/* nullprpl doesn't support file transfer...yet... */
+static gboolean nullprpl_can_receive_file(PurpleConnection *gc,
+                                          const char *who) {
+  return FALSE;
+}
+
+static gboolean nullprpl_offline_message(const PurpleBuddy *buddy) {
+  purple_debug_info("nullprpl",
+                    "reporting that offline messages are supported for %s\n",
+                    buddy->name);
+  return TRUE;
+}
+
+
+/*
+ * prpl stuff. see prpl.h for more information.
+ */
+
+static PurplePluginProtocolInfo prpl_info =
+{
+  OPT_PROTO_NO_PASSWORD | OPT_PROTO_CHAT_TOPIC,  /* options */
+  NULL,               /* user_splits, initialized in nullprpl_init() */
+  NULL,               /* protocol_options, initialized in nullprpl_init() */
+  {   /* icon_spec, a PurpleBuddyIconSpec */
+      "png,jpg,gif",                   /* format */
+      0,                               /* min_width */
+      0,                               /* min_height */
+      128,                             /* max_width */
+      128,                             /* max_height */
+      10000,                           /* max_filesize */
+      PURPLE_ICON_SCALE_DISPLAY,       /* scale_rules */
+  },
+  nullprpl_list_icon,                  /* list_icon */
+  nullprpl_list_emblem,                /* list_emblem */
+  nullprpl_status_text,                /* status_text */
+  nullprpl_tooltip_text,               /* tooltip_text */
+  nullprpl_status_types,               /* status_types */
+  nullprpl_blist_node_menu,            /* blist_node_menu */
+  nullprpl_chat_info,                  /* chat_info */
+  nullprpl_chat_info_defaults,         /* chat_info_defaults */
+  nullprpl_login,                      /* login */
+  nullprpl_close,                      /* close */
+  nullprpl_send_im,                    /* send_im */
+  nullprpl_set_info,                   /* set_info */
+  nullprpl_send_typing,                /* send_typing */
+  nullprpl_get_info,                   /* get_info */
+  nullprpl_set_status,                 /* set_status */
+  nullprpl_set_idle,                   /* set_idle */
+  nullprpl_change_passwd,              /* change_passwd */
+  nullprpl_add_buddy,                  /* add_buddy */
+  nullprpl_add_buddies,                /* add_buddies */
+  nullprpl_remove_buddy,               /* remove_buddy */
+  nullprpl_remove_buddies,             /* remove_buddies */
+  nullprpl_add_permit,                 /* add_permit */
+  nullprpl_add_deny,                   /* add_deny */
+  nullprpl_rem_permit,                 /* rem_permit */
+  nullprpl_rem_deny,                   /* rem_deny */
+  nullprpl_set_permit_deny,            /* set_permit_deny */
+  nullprpl_join_chat,                  /* join_chat */
+  nullprpl_reject_chat,                /* reject_chat */
+  nullprpl_get_chat_name,              /* get_chat_name */
+  nullprpl_chat_invite,                /* chat_invite */
+  nullprpl_chat_leave,                 /* chat_leave */
+  nullprpl_chat_whisper,               /* chat_whisper */
+  nullprpl_chat_send,                  /* chat_send */
+  NULL,                                /* keepalive */
+  nullprpl_register_user,              /* register_user */
+  nullprpl_get_cb_info,                /* get_cb_info */
+  NULL,                                /* get_cb_away */
+  nullprpl_alias_buddy,                /* alias_buddy */
+  nullprpl_group_buddy,                /* group_buddy */
+  nullprpl_rename_group,               /* rename_group */
+  NULL,                                /* buddy_free */
+  nullprpl_convo_closed,               /* convo_closed */
+  nullprpl_normalize,                  /* normalize */
+  nullprpl_set_buddy_icon,             /* set_buddy_icon */
+  nullprpl_remove_group,               /* remove_group */
+  NULL,                                /* get_cb_real_name */
+  nullprpl_set_chat_topic,             /* set_chat_topic */
+  NULL,                                /* find_blist_chat */
+  nullprpl_roomlist_get_list,          /* roomlist_get_list */
+  nullprpl_roomlist_cancel,            /* roomlist_cancel */
+  nullprpl_roomlist_expand_category,   /* roomlist_expand_category */
+  nullprpl_can_receive_file,           /* can_receive_file */
+  NULL,                                /* send_file */
+  NULL,                                /* new_xfer */
+  nullprpl_offline_message,            /* offline_message */
+  NULL,                                /* whiteboard_prpl_ops */
+  NULL,                                /* send_raw */
+  NULL,                                /* roomlist_room_serialize */
+  NULL,                                /* padding... */
+  NULL,
+  NULL,
+  NULL,
+};
+
+static void nullprpl_init(PurplePlugin *plugin)
+{
+  /* see accountopt.h for information about user splits and protocol options */
+  PurpleAccountUserSplit *split = purple_account_user_split_new(
+    _("Example user split (unused)"),  /* text shown to user */
+    "default",                         /* default value */
+    '@');                              /* field separator */
+  PurpleAccountOption *option = purple_account_option_string_new(
+    _("Example option (unused)"),      /* text shown to user */
+    "example",                         /* pref name */
+    "default");                        /* default value */
+
+  purple_debug_info("nullprpl", "starting up\n");
+
+  prpl_info.user_splits = g_list_append(NULL, split);
+  prpl_info.protocol_options = g_list_append(NULL, option);
+
+  /* register whisper chat command, /msg */
+  purple_cmd_register("msg",
+                    "ws",                /* args: recipient and message */
+                    PURPLE_CMD_P_DEFAULT,  /* priority */
+                    PURPLE_CMD_FLAG_CHAT,
+                    "prpl-null",
+                    send_whisper,
+                    "msg &lt;username&gt; &lt;message&gt;: send a private message, aka a whisper",
+                    NULL);               /* userdata */
+
+  /* get ready to store offline messages */
+  goffline_messages = g_hash_table_new_full(g_str_hash,  /* hash fn */
+                                            g_str_equal, /* key comparison fn */
+                                            g_free,      /* key free fn */
+                                            NULL);       /* value free fn */
+
+  _null_protocol = plugin;
+}
+
+static void nullprpl_destroy(PurplePlugin *plugin) {
+  purple_debug_info("nullprpl", "shutting down\n");
+}
+
+
+static PurplePluginInfo info =
+{
+  PURPLE_PLUGIN_MAGIC,                                     /* magic */
+  PURPLE_MAJOR_VERSION,                                    /* major_version */
+  PURPLE_MINOR_VERSION,                                    /* minor_version */
+  PURPLE_PLUGIN_PROTOCOL,                                  /* type */
+  NULL,                                                    /* ui_requirement */
+  0,                                                       /* flags */
+  NULL,                                                    /* dependencies */
+  PURPLE_PRIORITY_DEFAULT,                                 /* priority */
+  NULLPRPL_ID,                                             /* id */
+  "Nullprpl",                                              /* name */
+  "0.3",                                                   /* version */
+  "Null Protocol Plugin",                                  /* summary */
+  "Null Protocol Plugin",                                  /* description */
+  "Ryan Barrett <nullprpl@ryanb.org>",                     /* author */
+  "http://snarfed.org/space/pidgin+null+protocol+plugin",  /* homepage */
+  NULL,                                                    /* load */
+  NULL,                                                    /* unload */
+  nullprpl_destroy,                                        /* destroy */
+  NULL,                                                    /* ui_info */
+  &prpl_info,                                              /* extra_info */
+  NULL,                                                    /* prefs_info */
+  nullprpl_actions,                                        /* actions */
+  NULL,                                                    /* padding... */
+  NULL,
+  NULL,
+  NULL,
+};
+
+PURPLE_INIT_PLUGIN(null, nullprpl_init, info);
--- a/libpurple/protocols/oscar/.todo	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/.todo	Mon Jun 18 01:48:35 2007 +0000
@@ -15,16 +15,10 @@
             <note priority="veryhigh" time="1036040919">
                 some way to close direct connect w/out closing convo.
             </note>
-            <note priority="low" time="1036040970">
-                canceled direct im should still allow new attempt
-            </note>
             <note priority="low" time="1036041084">
                 failed direct im attempt should allow new attempt some way to cancel an attempt that isn't happening
             </note>
         </note>
-        <note priority="low" time="1036041105">
-            Colors in Chat room are wrong (using Gold too much)
-        </note>
         <note priority="verylow" time="1036041121">
             Voice Chat
         </note>
@@ -44,7 +38,7 @@
             color support
         </note>
         <note priority="high" time="1036041251">
-            set status message and of course when gaim can set them, it needs to be able to get the ones it sets. (yes this is redundant. its a reflection of my current mood)
+            set status message and of course when libpurple can set them, it needs to be able to get the ones it sets. (yes this is redundant. its a reflection of my current mood)
         </note>
         <note priority="medium" time="1036041165">
             Chat (this is different from aim chat)
@@ -66,6 +60,6 @@
         </note>
     </note>
     <note priority="medium" time="1036040870">
-        The order of groups and buddies in the server list is not updated when groups and buddies are re-arranged locally in Gaim.
+        The order of groups and buddies in the server list is not updated when groups and buddies are re-arranged locally in libpurple.
     </note>
 </todo>
--- a/libpurple/protocols/oscar/AUTHORS	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/AUTHORS	Mon Jun 18 01:48:35 2007 +0000
@@ -35,7 +35,7 @@
 N: Eric Warmenhoven
 T: 1998-2001
 E: warmenhoven a.t linux d.o.t com
-D: Some OFT info, author of the faim interface for gaim
+D: Some OFT info, initial author of the libpurple-side of the oscar protocol plugin
 
 N: Brock Wilcox
 T: 1998-2001
--- a/libpurple/protocols/oscar/Makefile.am	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/Makefile.am	Mon Jun 18 01:48:35 2007 +0000
@@ -52,15 +52,10 @@
 if STATIC_OSCAR
 
 st = -DPURPLE_STATIC_PRPL
-noinst_LIBRARIES   = liboscar.a libaim.a libicq.a
-liboscar_a_SOURCES = $(OSCARSOURCES)
-liboscar_a_CFLAGS  = $(AM_CFLAGS)
+noinst_LIBRARIES   = liboscar.a
 
-libaim_a_CFLAGS = $(AM_CFLAGS)
-libaim_a_SOURCES = libaim.c
-
-libicq_a_CFLAGS = $(AM_CFLAGS)
-libicq_a_SOURCES = libicq.c
+liboscar_a_SOURCES = $(OSCARSOURCES) libaim.c libicq.c
+liboscar_a_CFLAGS  = $(AM_CFLAGS)
 
 else
 
--- a/libpurple/protocols/oscar/family_admin.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/family_admin.c	Mon Jun 18 01:48:35 2007 +0000
@@ -125,17 +125,17 @@
 {
 	FlapFrame *fr;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	fr = flap_frame_new(od, 0x02, 10+2+2+strlen(newnick));
 
 	snacid = aim_cachesnac(od, 0x0007, 0x0004, 0x0000, NULL, 0);
 	aim_putsnac(&fr->data, 0x0007, 0x0004, 0x0000, snacid);
 
-	aim_tlvlist_add_str(&tl, 0x0001, newnick);
+	aim_tlvlist_add_str(&tlvlist, 0x0001, newnick);
 
-	aim_tlvlist_write(&fr->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&fr->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, fr);
 
@@ -151,7 +151,7 @@
 aim_admin_changepasswd(OscarData *od, FlapConnection *conn, const char *newpw, const char *curpw)
 {
 	FlapFrame *fr;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 	aim_snacid_t snacid;
 
 	fr = flap_frame_new(od, 0x02, 10+4+strlen(curpw)+4+strlen(newpw));
@@ -160,13 +160,13 @@
 	aim_putsnac(&fr->data, 0x0007, 0x0004, 0x0000, snacid);
 
 	/* new password TLV t(0002) */
-	aim_tlvlist_add_str(&tl, 0x0002, newpw);
+	aim_tlvlist_add_str(&tlvlist, 0x0002, newpw);
 
 	/* current password TLV t(0012) */
-	aim_tlvlist_add_str(&tl, 0x0012, curpw);
+	aim_tlvlist_add_str(&tlvlist, 0x0012, curpw);
 
-	aim_tlvlist_write(&fr->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&fr->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, fr);
 
@@ -182,17 +182,17 @@
 {
 	FlapFrame *fr;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	fr = flap_frame_new(od, 0x02, 10+2+2+strlen(newemail));
 
 	snacid = aim_cachesnac(od, 0x0007, 0x0004, 0x0000, NULL, 0);
 	aim_putsnac(&fr->data, 0x0007, 0x0004, 0x0000, snacid);
 
-	aim_tlvlist_add_str(&tl, 0x0011, newemail);
+	aim_tlvlist_add_str(&tlvlist, 0x0011, newemail);
 
-	aim_tlvlist_write(&fr->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&fr->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, fr);
 
@@ -223,17 +223,17 @@
 	int ret = 0;
 	aim_rxcallback_t userfunc;
 	guint16 status;
-	/* aim_tlvlist_t *tl; */
+	/* GSList *tlvlist; */
 
 	status = byte_stream_get16(bs);
 	/* Status is 0x0013 if unable to confirm at this time */
 
-	/* tl = aim_tlvlist_read(bs); */
+	/* tlvlist = aim_tlvlist_read(bs); */
 
 	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
 		ret = userfunc(od, conn, frame, status);
 
-	/* aim_tlvlist_free(&tl); */
+	/* aim_tlvlist_free(tlvlist); */
 
 	return ret;
 }
--- a/libpurple/protocols/oscar/family_alert.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/family_alert.c	Mon Jun 18 01:48:35 2007 +0000
@@ -98,7 +98,7 @@
 	int ret = 0;
 	aim_rxcallback_t userfunc;
 	struct aim_emailinfo *new;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	guint8 *cookie8, *cookie16;
 	int tmp, havenewmail = 0; /* Used to tell the client we have _new_ mail */
 
@@ -152,7 +152,7 @@
 	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
 		ret = userfunc(od, conn, frame, new, havenewmail, alertitle, (alerturl ? alerturl + 2 : NULL));
 
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	g_free(alertitle);
 	g_free(alerturl);
--- a/libpurple/protocols/oscar/family_auth.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/family_auth.c	Mon Jun 18 01:48:35 2007 +0000
@@ -129,7 +129,7 @@
 goddamnicq2(OscarData *od, FlapConnection *conn, const char *sn, const char *password, ClientInfo *ci)
 {
 	FlapFrame *frame;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 	int passwdlen;
 	guint8 *password_encoded;
 
@@ -143,24 +143,24 @@
 	aim_encode_password(password, password_encoded);
 
 	byte_stream_put32(&frame->data, 0x00000001); /* FLAP Version */
-	aim_tlvlist_add_str(&tl, 0x0001, sn);
-	aim_tlvlist_add_raw(&tl, 0x0002, passwdlen, password_encoded);
+	aim_tlvlist_add_str(&tlvlist, 0x0001, sn);
+	aim_tlvlist_add_raw(&tlvlist, 0x0002, passwdlen, password_encoded);
 
 	if (ci->clientstring)
-		aim_tlvlist_add_str(&tl, 0x0003, ci->clientstring);
-	aim_tlvlist_add_16(&tl, 0x0016, (guint16)ci->clientid);
-	aim_tlvlist_add_16(&tl, 0x0017, (guint16)ci->major);
-	aim_tlvlist_add_16(&tl, 0x0018, (guint16)ci->minor);
-	aim_tlvlist_add_16(&tl, 0x0019, (guint16)ci->point);
-	aim_tlvlist_add_16(&tl, 0x001a, (guint16)ci->build);
-	aim_tlvlist_add_32(&tl, 0x0014, (guint32)ci->distrib); /* distribution chan */
-	aim_tlvlist_add_str(&tl, 0x000f, ci->lang);
-	aim_tlvlist_add_str(&tl, 0x000e, ci->country);
+		aim_tlvlist_add_str(&tlvlist, 0x0003, ci->clientstring);
+	aim_tlvlist_add_16(&tlvlist, 0x0016, (guint16)ci->clientid);
+	aim_tlvlist_add_16(&tlvlist, 0x0017, (guint16)ci->major);
+	aim_tlvlist_add_16(&tlvlist, 0x0018, (guint16)ci->minor);
+	aim_tlvlist_add_16(&tlvlist, 0x0019, (guint16)ci->point);
+	aim_tlvlist_add_16(&tlvlist, 0x001a, (guint16)ci->build);
+	aim_tlvlist_add_32(&tlvlist, 0x0014, (guint32)ci->distrib); /* distribution chan */
+	aim_tlvlist_add_str(&tlvlist, 0x000f, ci->lang);
+	aim_tlvlist_add_str(&tlvlist, 0x000e, ci->country);
 
-	aim_tlvlist_write(&frame->data, &tl);
+	aim_tlvlist_write(&frame->data, &tlvlist);
 
 	g_free(password_encoded);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -201,7 +201,7 @@
 aim_send_login(OscarData *od, FlapConnection *conn, const char *sn, const char *password, gboolean truncate_pass, ClientInfo *ci, const char *key)
 {
 	FlapFrame *frame;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 	guint8 digest[16];
 	aim_snacid_t snacid;
 	size_t password_len;
@@ -220,7 +220,7 @@
 	snacid = aim_cachesnac(od, 0x0017, 0x0002, 0x0000, NULL, 0);
 	aim_putsnac(&frame->data, 0x0017, 0x0002, 0x0000, snacid);
 
-	aim_tlvlist_add_str(&tl, 0x0001, sn);
+	aim_tlvlist_add_str(&tlvlist, 0x0001, sn);
 
 	/* Truncate ICQ and AOL passwords, if necessary */
 	password_len = strlen(password);
@@ -231,32 +231,32 @@
 
 	aim_encode_password_md5(password, password_len, key, digest);
 
-	aim_tlvlist_add_raw(&tl, 0x0025, 16, digest);
+	aim_tlvlist_add_raw(&tlvlist, 0x0025, 16, digest);
 
 #ifndef USE_OLD_MD5
-	aim_tlvlist_add_noval(&tl, 0x004c);
+	aim_tlvlist_add_noval(&tlvlist, 0x004c);
 #endif
 
 	if (ci->clientstring)
-		aim_tlvlist_add_str(&tl, 0x0003, ci->clientstring);
-	aim_tlvlist_add_16(&tl, 0x0016, (guint16)ci->clientid);
-	aim_tlvlist_add_16(&tl, 0x0017, (guint16)ci->major);
-	aim_tlvlist_add_16(&tl, 0x0018, (guint16)ci->minor);
-	aim_tlvlist_add_16(&tl, 0x0019, (guint16)ci->point);
-	aim_tlvlist_add_16(&tl, 0x001a, (guint16)ci->build);
-	aim_tlvlist_add_32(&tl, 0x0014, (guint32)ci->distrib);
-	aim_tlvlist_add_str(&tl, 0x000f, ci->lang);
-	aim_tlvlist_add_str(&tl, 0x000e, ci->country);
+		aim_tlvlist_add_str(&tlvlist, 0x0003, ci->clientstring);
+	aim_tlvlist_add_16(&tlvlist, 0x0016, (guint16)ci->clientid);
+	aim_tlvlist_add_16(&tlvlist, 0x0017, (guint16)ci->major);
+	aim_tlvlist_add_16(&tlvlist, 0x0018, (guint16)ci->minor);
+	aim_tlvlist_add_16(&tlvlist, 0x0019, (guint16)ci->point);
+	aim_tlvlist_add_16(&tlvlist, 0x001a, (guint16)ci->build);
+	aim_tlvlist_add_32(&tlvlist, 0x0014, (guint32)ci->distrib);
+	aim_tlvlist_add_str(&tlvlist, 0x000f, ci->lang);
+	aim_tlvlist_add_str(&tlvlist, 0x000e, ci->country);
 
 	/*
 	 * If set, old-fashioned buddy lists will not work. You will need
 	 * to use SSI.
 	 */
-	aim_tlvlist_add_8(&tl, 0x004a, 0x01);
+	aim_tlvlist_add_8(&tlvlist, 0x004a, 0x01);
 
-	aim_tlvlist_write(&frame->data, &tl);
+	aim_tlvlist_write(&frame->data, &tlvlist);
 
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -274,7 +274,7 @@
 static int
 parse(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
 {
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	aim_rxcallback_t userfunc;
 	struct aim_authresp_info *info;
 	int ret = 0;
@@ -402,7 +402,7 @@
 	if ((userfunc = aim_callhandler(od, snac ? snac->family : 0x0017, snac ? snac->subtype : 0x0003)))
 		ret = userfunc(od, conn, frame, info);
 
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
@@ -471,7 +471,7 @@
 {
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	if (!od || !conn || !sn)
 		return -EINVAL;
@@ -486,16 +486,16 @@
 	snacid = aim_cachesnac(od, 0x0017, 0x0006, 0x0000, NULL, 0);
 	aim_putsnac(&frame->data, 0x0017, 0x0006, 0x0000, snacid);
 
-	aim_tlvlist_add_str(&tl, 0x0001, sn);
+	aim_tlvlist_add_str(&tlvlist, 0x0001, sn);
 
 	/* Tell the server we support SecurID logins. */
-	aim_tlvlist_add_noval(&tl, 0x004b);
+	aim_tlvlist_add_noval(&tlvlist, 0x004b);
 
 	/* Unknown.  Sent in recent WinAIM clients.*/
-	aim_tlvlist_add_noval(&tl, 0x005a);
+	aim_tlvlist_add_noval(&tlvlist, 0x005a);
 
-	aim_tlvlist_write(&frame->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -517,7 +517,7 @@
 	int keylen, ret = 1;
 	aim_rxcallback_t userfunc;
 	char *keystr;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	gboolean truncate_pass;
 
 	keylen = byte_stream_get16(bs);
@@ -539,7 +539,7 @@
 		ret = userfunc(od, conn, frame, keystr, (int)truncate_pass);
 
 	g_free(keystr);
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
--- a/libpurple/protocols/oscar/family_bos.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/family_bos.c	Mon Jun 18 01:48:35 2007 +0000
@@ -39,7 +39,7 @@
 static int rights(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
 {
 	aim_rxcallback_t userfunc;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	guint16 maxpermits = 0, maxdenies = 0;
 	int ret = 0;
 
@@ -63,7 +63,7 @@
 	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
 		ret = userfunc(od, conn, frame, maxpermits, maxdenies);
 
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
--- a/libpurple/protocols/oscar/family_buddy.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/family_buddy.c	Mon Jun 18 01:48:35 2007 +0000
@@ -47,7 +47,7 @@
 rights(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
 {
 	aim_rxcallback_t userfunc;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	guint16 maxbuddies = 0, maxwatchers = 0;
 	int ret = 0;
 
@@ -82,7 +82,7 @@
 	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
 		ret = userfunc(od, conn, frame, maxbuddies, maxwatchers);
 
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
--- a/libpurple/protocols/oscar/family_chat.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/family_chat.c	Mon Jun 18 01:48:35 2007 +0000
@@ -159,7 +159,7 @@
 	char *roomname;
 	struct aim_chat_roominfo roominfo;
 	guint16 tlvcount = 0;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	aim_tlv_t *tlv;
 	char *roomdesc;
 	guint16 flags;
@@ -309,7 +309,7 @@
 	g_free(userinfo);
 	g_free(roomname);
 	g_free(roomdesc);
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
@@ -357,7 +357,7 @@
 	IcbmCookie *cookie;
 	aim_snacid_t snacid;
 	guint8 ckstr[8];
-	aim_tlvlist_t *tlvlist = NULL, *inner_tlvlist = NULL;
+	GSList *tlvlist = NULL, *inner_tlvlist = NULL;
 
 	if (!od || !conn || !msg || (msglen <= 0))
 		return 0;
@@ -430,8 +430,8 @@
 
 	aim_tlvlist_write(&frame->data, &tlvlist);
 
-	aim_tlvlist_free(&inner_tlvlist);
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(inner_tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -471,7 +471,7 @@
 	aim_userinfo_t userinfo;
 	guint8 cookie[8];
 	guint16 channel;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	char *msg = NULL;
 	int len = 0;
 	char *encoding = NULL, *language = NULL;
@@ -536,7 +536,7 @@
 	tlv = aim_tlv_gettlv(tlvlist, 0x0005, 1);
 	if (tlv != NULL)
 	{
-		aim_tlvlist_t *inner_tlvlist;
+		GSList *inner_tlvlist;
 		aim_tlv_t *inner_tlv;
 
 		byte_stream_init(&tbs, tlv->value, tlv->length);
@@ -562,7 +562,7 @@
 		 */
 		language = aim_tlv_getstr(inner_tlvlist, 0x0003, 1);
 
-		aim_tlvlist_free(&inner_tlvlist);
+		aim_tlvlist_free(inner_tlvlist);
 	}
 
 	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
@@ -572,7 +572,7 @@
 	g_free(msg);
 	g_free(encoding);
 	g_free(language);
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
--- a/libpurple/protocols/oscar/family_chatnav.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/family_chatnav.c	Mon Jun 18 01:48:35 2007 +0000
@@ -50,7 +50,7 @@
 	static const char charset[] = {"us-ascii"};
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	frame = flap_frame_new(od, 0x02, 1152);
 
@@ -85,15 +85,15 @@
 	/* detail level */
 	byte_stream_put8(&frame->data, 0x01);
 
-	aim_tlvlist_add_str(&tl, 0x00d3, name);
-	aim_tlvlist_add_str(&tl, 0x00d6, charset);
-	aim_tlvlist_add_str(&tl, 0x00d7, lang);
+	aim_tlvlist_add_str(&tlvlist, 0x00d3, name);
+	aim_tlvlist_add_str(&tlvlist, 0x00d6, charset);
+	aim_tlvlist_add_str(&tlvlist, 0x00d7, lang);
 
 	/* tlvcount */
-	byte_stream_put16(&frame->data, aim_tlvlist_count(&tl));
-	aim_tlvlist_write(&frame->data, &tl);
+	byte_stream_put16(&frame->data, aim_tlvlist_count(tlvlist));
+	aim_tlvlist_write(&frame->data, &tlvlist);
 
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -109,7 +109,7 @@
 	int curexchange;
 	aim_tlv_t *exchangetlv;
 	guint8 maxrooms = 0;
-	aim_tlvlist_t *tlvlist, *innerlist;
+	GSList *tlvlist, *innerlist;
 
 	tlvlist = aim_tlvlist_read(bs);
 
@@ -290,7 +290,7 @@
 		}
 #endif
 
-		aim_tlvlist_free(&innerlist);
+		aim_tlvlist_free(innerlist);
 	}
 
 	/*
@@ -307,7 +307,7 @@
 		g_free(exchanges[curexchange].lang2);
 	}
 	g_free(exchanges);
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
@@ -316,7 +316,7 @@
 parseinfo_create(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs, aim_snac_t *snac2)
 {
 	aim_rxcallback_t userfunc;
-	aim_tlvlist_t *tlvlist, *innerlist;
+	GSList *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;
@@ -330,7 +330,7 @@
 
 	if (!(bigblock = aim_tlv_gettlv(tlvlist, 0x0004, 1))) {
 		purple_debug_misc("oscar", "no bigblock in top tlv in create room response\n");
-		aim_tlvlist_free(&tlvlist);
+		aim_tlvlist_free(tlvlist);
 		return 0;
 	}
 
@@ -344,7 +344,7 @@
 
 	if (detaillevel != 0x02) {
 		purple_debug_misc("oscar", "unknown detaillevel in create room response (0x%02x)\n", detaillevel);
-		aim_tlvlist_free(&tlvlist);
+		aim_tlvlist_free(tlvlist);
 		g_free(ck);
 		return 0;
 	}
@@ -381,8 +381,8 @@
 	g_free(ck);
 	g_free(name);
 	g_free(fqcn);
-	aim_tlvlist_free(&innerlist);
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(innerlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
--- a/libpurple/protocols/oscar/family_feedbag.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/family_feedbag.c	Mon Jun 18 01:48:35 2007 +0000
@@ -110,7 +110,7 @@
  * @param data The additional data for the new item.
  * @return A pointer to the newly created item.
  */
-static struct aim_ssi_item *aim_ssi_itemlist_add(struct aim_ssi_item **list, const char *name, guint16 gid, guint16 bid, guint16 type, aim_tlvlist_t *data)
+static struct aim_ssi_item *aim_ssi_itemlist_add(struct aim_ssi_item **list, const char *name, guint16 gid, guint16 bid, guint16 type, GSList *data)
 {
 	gboolean exists;
 	struct aim_ssi_item *cur, *new;
@@ -214,7 +214,7 @@
 
 	/* Free the removed item */
 	g_free(del->name);
-	aim_tlvlist_free(&del->data);
+	aim_tlvlist_free(del->data);
 	g_free(del);
 
 	return 0;
@@ -610,7 +610,7 @@
 		del = cur;
 		cur = cur->next;
 		g_free(del->name);
-		aim_tlvlist_free(&del->data);
+		aim_tlvlist_free(del->data);
 		g_free(del);
 	}
 
@@ -619,7 +619,7 @@
 		del = cur;
 		cur = cur->next;
 		g_free(del->name);
-		aim_tlvlist_free(&del->data);
+		aim_tlvlist_free(del->data);
 		g_free(del);
 	}
 
@@ -670,7 +670,7 @@
 				aim_ssi_deldeny(od, NULL);
 		} else if ((cur->type == AIM_SSI_TYPE_BUDDY) && ((cur->gid == 0x0000) || (!aim_ssi_itemlist_find(od->ssi.local, cur->gid, 0x0000)))) {
 			char *alias = aim_ssi_getalias(od->ssi.local, NULL, cur->name);
-			aim_ssi_addbuddy(od, cur->name, "orphans", alias, NULL, NULL, 0);
+			aim_ssi_addbuddy(od, cur->name, "orphans", NULL, alias, NULL, NULL, FALSE);
 			aim_ssi_delbuddy(od, cur->name, NULL);
 			g_free(alias);
 		}
@@ -721,15 +721,15 @@
  * @param od The oscar odion.
  * @param name The name of the item.
  * @param group The group of the item.
+ * @param data A TLV list to use as the additional data for this item.
  * @param alias The alias/nickname of the item, or NULL.
  * @param comment The buddy comment for the item, or NULL.
  * @param smsnum The locally assigned SMS number, or NULL.
  * @return Return 0 if no errors, otherwise return the error number.
  */
-int aim_ssi_addbuddy(OscarData *od, const char *name, const char *group, const char *alias, const char *comment, const char *smsnum, int needauth)
+int aim_ssi_addbuddy(OscarData *od, const char *name, const char *group, GSList *data, const char *alias, const char *comment, const char *smsnum, gboolean needauth)
 {
 	struct aim_ssi_item *parent;
-	aim_tlvlist_t *data = NULL;
 
 	if (!od || !name || !group)
 		return -EINVAL;
@@ -750,16 +750,16 @@
 	/* Create a TLV list for the new buddy */
 	if (needauth)
 		aim_tlvlist_add_noval(&data, 0x0066);
-	if (alias)
+	if (alias != NULL)
 		aim_tlvlist_add_str(&data, 0x0131, alias);
-	if (smsnum)
+	if (smsnum != NULL)
 		aim_tlvlist_add_str(&data, 0x013a, smsnum);
-	if (comment)
+	if (comment != NULL)
 		aim_tlvlist_add_str(&data, 0x013c, comment);
 
 	/* Add that bad boy */
 	aim_ssi_itemlist_add(&od->ssi.local, name, parent->gid, 0xFFFF, AIM_SSI_TYPE_BUDDY, data);
-	aim_tlvlist_free(&data);
+	aim_tlvlist_free(data);
 
 	/* Modify the parent group */
 	aim_ssi_itemlist_rebuildgroup(od->ssi.local, group);
@@ -920,16 +920,22 @@
  */
 int aim_ssi_movebuddy(OscarData *od, const char *oldgn, const char *newgn, const char *sn)
 {
-	char *alias;
-	gboolean waitingforauth;
+	struct aim_ssi_item *buddy;
+	GSList *data;
+
+	/* Find the buddy */
+	buddy = aim_ssi_itemlist_finditem(od->ssi.local, oldgn, sn, AIM_SSI_TYPE_BUDDY);
+	if (buddy == NULL)
+		return -EINVAL;
 
-	alias = aim_ssi_getalias(od->ssi.local, oldgn, sn);
-	waitingforauth = aim_ssi_waitingforauth(od->ssi.local, oldgn, sn);
+	/* Make a copy of the buddy's TLV list */
+	data = aim_tlvlist_copy(buddy->data);
 
+	/* Delete the old item */
 	aim_ssi_delbuddy(od, sn, oldgn);
-	aim_ssi_addbuddy(od, sn, newgn, alias, NULL, NULL, waitingforauth);
 
-	g_free(alias);
+	/* Add the new item using the EXACT SAME TLV list */
+	aim_ssi_addbuddy(od, sn, newgn, data, NULL, NULL, NULL, FALSE);
 
 	return 0;
 }
@@ -1172,7 +1178,7 @@
 {
 	int ret = 0, i;
 	aim_rxcallback_t userfunc;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	aim_tlv_t *tlv;
 	ByteStream bstream;
 	guint16 *maxitems;
@@ -1182,7 +1188,7 @@
 
 	/* TLV 0x0004 contains the maximum number of each item */
 	if (!(tlv = aim_tlv_gettlv(tlvlist, 0x0004, 1))) {
-		aim_tlvlist_free(&tlvlist);
+		aim_tlvlist_free(tlvlist);
 		return 0;
 	}
 
@@ -1196,7 +1202,7 @@
 	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
 		ret = userfunc(od, conn, frame, tlv->length/2, maxitems);
 
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 	g_free(maxitems);
 
 	return ret;
@@ -1267,7 +1273,7 @@
 	guint8 fmtver; /* guess */
 	guint16 namelen, gid, bid, type;
 	char *name;
-	aim_tlvlist_t *data;
+	GSList *data;
 
 	fmtver = byte_stream_get8(bs); /* Version of ssi data.  Should be 0x00 */
 	od->ssi.numitems += byte_stream_get16(bs); /* # of items in this SSI SNAC */
@@ -1284,7 +1290,7 @@
 		data = aim_tlvlist_readlen(bs, byte_stream_get16(bs));
 		aim_ssi_itemlist_add(&od->ssi.official, name, gid, bid, type, data);
 		g_free(name);
-		aim_tlvlist_free(&data);
+		aim_tlvlist_free(data);
 	}
 
 	/* Read in the timestamp */
@@ -1352,7 +1358,7 @@
 		if (cur->item->name)
 			snaclen += strlen(cur->item->name);
 		if (cur->item->data)
-			snaclen += aim_tlvlist_size(&cur->item->data);
+			snaclen += aim_tlvlist_size(cur->item->data);
 	}
 
 	frame = flap_frame_new(od, 0x02, snaclen);
@@ -1367,7 +1373,7 @@
 		byte_stream_put16(&frame->data, cur->item->gid);
 		byte_stream_put16(&frame->data, cur->item->bid);
 		byte_stream_put16(&frame->data, cur->item->type);
-		byte_stream_put16(&frame->data, cur->item->data ? aim_tlvlist_size(&cur->item->data) : 0);
+		byte_stream_put16(&frame->data, cur->item->data ? aim_tlvlist_size(cur->item->data) : 0);
 		if (cur->item->data)
 			aim_tlvlist_write(&frame->data, &cur->item->data);
 	}
@@ -1389,7 +1395,7 @@
 	aim_rxcallback_t userfunc;
 	char *name;
 	guint16 len, gid, bid, type;
-	aim_tlvlist_t *data;
+	GSList *data;
 
 	while (byte_stream_empty(bs)) {
 		if ((len = byte_stream_get16(bs)))
@@ -1406,7 +1412,7 @@
 
 		aim_ssi_itemlist_add(&od->ssi.local, name, gid, bid, type, data);
 		aim_ssi_itemlist_add(&od->ssi.official, name, gid, bid, type, data);
-		aim_tlvlist_free(&data);
+		aim_tlvlist_free(data);
 
 		if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
 			ret = userfunc(od, conn, frame, type, name);
@@ -1428,7 +1434,7 @@
 	aim_rxcallback_t userfunc;
 	char *name;
 	guint16 len, gid, bid, type;
-	aim_tlvlist_t *data;
+	GSList *data;
 	struct aim_ssi_item *item;
 
 	while (byte_stream_empty(bs)) {
@@ -1453,7 +1459,7 @@
 				strcpy(item->name, name);
 			} else
 				item->name = NULL;
-			aim_tlvlist_free(&item->data);
+			aim_tlvlist_free(item->data);
 			item->data = aim_tlvlist_copy(data);
 		}
 
@@ -1465,7 +1471,7 @@
 				strcpy(item->name, name);
 			} else
 				item->name = NULL;
-			aim_tlvlist_free(&item->data);
+			aim_tlvlist_free(item->data);
 			item->data = aim_tlvlist_copy(data);
 		}
 
@@ -1473,7 +1479,7 @@
 			ret = userfunc(od, conn, frame);
 
 		g_free(name);
-		aim_tlvlist_free(&data);
+		aim_tlvlist_free(data);
 	}
 
 	return ret;
@@ -1561,7 +1567,7 @@
 							strcpy(cur->item->name, cur1->name);
 						} else
 							cur->item->name = NULL;
-						aim_tlvlist_free(&cur->item->data);
+						aim_tlvlist_free(cur->item->data);
 						cur->item->data = aim_tlvlist_copy(cur1->data);
 					}
 				} else
@@ -1595,7 +1601,7 @@
 							strcpy(cur1->name, cur->item->name);
 						} else
 							cur1->name = NULL;
-						aim_tlvlist_free(&cur1->data);
+						aim_tlvlist_free(cur1->data);
 						cur1->data = aim_tlvlist_copy(cur->item->data);
 					}
 				} else
--- a/libpurple/protocols/oscar/family_icbm.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/family_icbm.c	Mon Jun 18 01:48:35 2007 +0000
@@ -451,7 +451,7 @@
 	IcbmCookie *msgcookie;
 	struct aim_invite_priv *priv;
 	guchar cookie[8];
-	aim_tlvlist_t *otl = NULL, *itl = NULL;
+	GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
 	ByteStream hdrbs;
 
 	if (!od || !(conn = flap_connection_findbygroup(od, 0x0004)))
@@ -498,19 +498,19 @@
 	byte_stream_putraw(&hdrbs, cookie, sizeof(cookie)); /* I think... */
 	byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_CHAT);
 
-	aim_tlvlist_add_16(&itl, 0x000a, 0x0001);
-	aim_tlvlist_add_noval(&itl, 0x000f);
-	aim_tlvlist_add_str(&itl, 0x000c, msg);
-	aim_tlvlist_add_chatroom(&itl, 0x2711, exchange, roomname, instance);
-	aim_tlvlist_write(&hdrbs, &itl);
-
-	aim_tlvlist_add_raw(&otl, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x000a, 0x0001);
+	aim_tlvlist_add_noval(&inner_tlvlist, 0x000f);
+	aim_tlvlist_add_str(&inner_tlvlist, 0x000c, msg);
+	aim_tlvlist_add_chatroom(&inner_tlvlist, 0x2711, exchange, roomname, instance);
+	aim_tlvlist_write(&hdrbs, &inner_tlvlist);
+
+	aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
 	g_free(hdrbs.data);
 
-	aim_tlvlist_write(&frame->data, &otl);
-
-	aim_tlvlist_free(&itl);
-	aim_tlvlist_free(&otl);
+	aim_tlvlist_write(&frame->data, &outer_tlvlist);
+
+	aim_tlvlist_free(inner_tlvlist);
+	aim_tlvlist_free(outer_tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -689,7 +689,7 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL, *itl = NULL;
+	GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
 	ByteStream hdrbs;
 
 	od = peer_conn->od;
@@ -705,7 +705,7 @@
 	/* ICBM header */
 	aim_im_puticbm(&frame->data, peer_conn->cookie, 0x0002, peer_conn->sn);
 
-	aim_tlvlist_add_noval(&tl, 0x0003);
+	aim_tlvlist_add_noval(&outer_tlvlist, 0x0003);
 
 	byte_stream_new(&hdrbs, 64);
 
@@ -714,16 +714,16 @@
 	byte_stream_putcaps(&hdrbs, peer_conn->type);
 
 	/* This TLV means "cancel!" */
-	aim_tlvlist_add_16(&itl, 0x000b, 0x0001);
-	aim_tlvlist_write(&hdrbs, &itl);
-
-	aim_tlvlist_add_raw(&tl, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x000b, 0x0001);
+	aim_tlvlist_write(&hdrbs, &inner_tlvlist);
+
+	aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
 	g_free(hdrbs.data);
 
-	aim_tlvlist_write(&frame->data, &tl);
-
-	aim_tlvlist_free(&itl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &outer_tlvlist);
+
+	aim_tlvlist_free(inner_tlvlist);
+	aim_tlvlist_free(outer_tlvlist);
 
 	flap_connection_send(conn, frame);
 }
@@ -775,7 +775,7 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL, *itl = NULL;
+	GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
 	ByteStream hdrbs;
 
 	conn = flap_connection_findbygroup(od, 0x0004);
@@ -790,7 +790,7 @@
 	/* ICBM header */
 	aim_im_puticbm(&frame->data, cookie, 0x0002, sn);
 
-	aim_tlvlist_add_noval(&tl, 0x0003);
+	aim_tlvlist_add_noval(&outer_tlvlist, 0x0003);
 
 	byte_stream_new(&hdrbs, 128);
 
@@ -798,20 +798,20 @@
 	byte_stream_putraw(&hdrbs, cookie, 8);
 	byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_DIRECTIM);
 
-	aim_tlvlist_add_raw(&itl, 0x0002, 4, ip);
-	aim_tlvlist_add_raw(&itl, 0x0003, 4, ip);
-	aim_tlvlist_add_16(&itl, 0x0005, port);
-	aim_tlvlist_add_16(&itl, 0x000a, requestnumber);
-	aim_tlvlist_add_noval(&itl, 0x000f);
-	aim_tlvlist_write(&hdrbs, &itl);
-
-	aim_tlvlist_add_raw(&tl, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x0002, 4, ip);
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x0003, 4, ip);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x0005, port);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x000a, requestnumber);
+	aim_tlvlist_add_noval(&inner_tlvlist, 0x000f);
+	aim_tlvlist_write(&hdrbs, &inner_tlvlist);
+
+	aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
 	g_free(hdrbs.data);
 
-	aim_tlvlist_write(&frame->data, &tl);
-
-	aim_tlvlist_free(&itl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &outer_tlvlist);
+
+	aim_tlvlist_free(inner_tlvlist);
+	aim_tlvlist_free(outer_tlvlist);
 
 	flap_connection_send(conn, frame);
 }
@@ -826,7 +826,7 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL, *itl = NULL;
+	GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
 	ByteStream hdrbs;
 	guint8 ip_comp[4];
 
@@ -842,7 +842,7 @@
 	/* ICBM header */
 	aim_im_puticbm(&frame->data, cookie, 0x0002, sn);
 
-	aim_tlvlist_add_noval(&tl, 0x0003);
+	aim_tlvlist_add_noval(&outer_tlvlist, 0x0003);
 
 	byte_stream_new(&hdrbs, 128);
 
@@ -850,30 +850,30 @@
 	byte_stream_putraw(&hdrbs, cookie, 8);
 	byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_DIRECTIM);
 
-	aim_tlvlist_add_raw(&itl, 0x0002, 4, ip);
-	aim_tlvlist_add_raw(&itl, 0x0003, 4, ip);
-	aim_tlvlist_add_16(&itl, 0x0005, pin);
-	aim_tlvlist_add_16(&itl, 0x000a, requestnumber);
-	aim_tlvlist_add_noval(&itl, 0x000f);
-	aim_tlvlist_add_noval(&itl, 0x0010);
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x0002, 4, ip);
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x0003, 4, ip);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x0005, pin);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x000a, requestnumber);
+	aim_tlvlist_add_noval(&inner_tlvlist, 0x000f);
+	aim_tlvlist_add_noval(&inner_tlvlist, 0x0010);
 
 	/* Send the bitwise complement of the port and ip.  As a check? */
 	ip_comp[0] = ~ip[0];
 	ip_comp[1] = ~ip[1];
 	ip_comp[2] = ~ip[2];
 	ip_comp[3] = ~ip[3];
-	aim_tlvlist_add_raw(&itl, 0x0016, 4, ip_comp);
-	aim_tlvlist_add_16(&itl, 0x0017, ~pin);
-
-	aim_tlvlist_write(&hdrbs, &itl);
-
-	aim_tlvlist_add_raw(&tl, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x0016, 4, ip_comp);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x0017, ~pin);
+
+	aim_tlvlist_write(&hdrbs, &inner_tlvlist);
+
+	aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
 	g_free(hdrbs.data);
 
-	aim_tlvlist_write(&frame->data, &tl);
-
-	aim_tlvlist_free(&itl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &outer_tlvlist);
+
+	aim_tlvlist_free(inner_tlvlist);
+	aim_tlvlist_free(outer_tlvlist);
 
 	flap_connection_send(conn, frame);
 }
@@ -888,7 +888,7 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL, *itl = NULL;
+	GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
 	ByteStream hdrbs;
 
 	conn = flap_connection_findbygroup(od, 0x0004);
@@ -903,7 +903,7 @@
 	/* ICBM header */
 	aim_im_puticbm(&frame->data, cookie, 0x0002, sn);
 
-	aim_tlvlist_add_noval(&tl, 0x0003);
+	aim_tlvlist_add_noval(&outer_tlvlist, 0x0003);
 
 	byte_stream_new(&hdrbs, 512);
 
@@ -911,11 +911,11 @@
 	byte_stream_putraw(&hdrbs, cookie, 8);
 	byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_SENDFILE);
 
-	aim_tlvlist_add_raw(&itl, 0x0002, 4, ip);
-	aim_tlvlist_add_raw(&itl, 0x0003, 4, ip);
-	aim_tlvlist_add_16(&itl, 0x0005, port);
-	aim_tlvlist_add_16(&itl, 0x000a, requestnumber);
-	aim_tlvlist_add_noval(&itl, 0x000f);
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x0002, 4, ip);
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x0003, 4, ip);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x0005, port);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x000a, requestnumber);
+	aim_tlvlist_add_noval(&inner_tlvlist, 0x000f);
 	/* TODO: Send 0x0016 and 0x0017 */
 
 #if 0
@@ -924,9 +924,9 @@
 	 *       redirect for a file receive (same conditions for
 	 *       sending 0x000f above)
 	 */
-	aim_tlvlist_add_raw(&itl, 0x000e, 2, "en");
-	aim_tlvlist_add_raw(&itl, 0x000d, 8, "us-ascii");
-	aim_tlvlist_add_raw(&itl, 0x000c, 24, "Please accept this file.");
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x000e, 2, "en");
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x000d, 8, "us-ascii");
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x000c, 24, "Please accept this file.");
 #endif
 
 	if (filename != NULL)
@@ -943,19 +943,19 @@
 		byte_stream_putstr(&bs, filename);
 		byte_stream_put8(&bs, 0x00);
 
-		aim_tlvlist_add_raw(&itl, 0x2711, bs.len, bs.data);
+		aim_tlvlist_add_raw(&inner_tlvlist, 0x2711, bs.len, bs.data);
 		g_free(bs.data);
 		/* End TLV t(2711) */
 	}
 
-	aim_tlvlist_write(&hdrbs, &itl);
-	aim_tlvlist_add_raw(&tl, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
+	aim_tlvlist_write(&hdrbs, &inner_tlvlist);
+	aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
 	g_free(hdrbs.data);
 
-	aim_tlvlist_write(&frame->data, &tl);
-
-	aim_tlvlist_free(&itl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &outer_tlvlist);
+
+	aim_tlvlist_free(inner_tlvlist);
+	aim_tlvlist_free(outer_tlvlist);
 
 	flap_connection_send(conn, frame);
 }
@@ -970,7 +970,7 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL, *itl = NULL;
+	GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
 	ByteStream hdrbs;
 	guint8 ip_comp[4];
 
@@ -986,7 +986,7 @@
 	/* ICBM header */
 	aim_im_puticbm(&frame->data, cookie, 0x0002, sn);
 
-	aim_tlvlist_add_noval(&tl, 0x0003);
+	aim_tlvlist_add_noval(&outer_tlvlist, 0x0003);
 
 	byte_stream_new(&hdrbs, 512);
 
@@ -994,20 +994,20 @@
 	byte_stream_putraw(&hdrbs, cookie, 8);
 	byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_SENDFILE);
 
-	aim_tlvlist_add_raw(&itl, 0x0002, 4, ip);
-	aim_tlvlist_add_raw(&itl, 0x0003, 4, ip);
-	aim_tlvlist_add_16(&itl, 0x0005, pin);
-	aim_tlvlist_add_16(&itl, 0x000a, requestnumber);
-	aim_tlvlist_add_noval(&itl, 0x000f);
-	aim_tlvlist_add_noval(&itl, 0x0010);
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x0002, 4, ip);
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x0003, 4, ip);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x0005, pin);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x000a, requestnumber);
+	aim_tlvlist_add_noval(&inner_tlvlist, 0x000f);
+	aim_tlvlist_add_noval(&inner_tlvlist, 0x0010);
 
 	/* Send the bitwise complement of the port and ip.  As a check? */
 	ip_comp[0] = ~ip[0];
 	ip_comp[1] = ~ip[1];
 	ip_comp[2] = ~ip[2];
 	ip_comp[3] = ~ip[3];
-	aim_tlvlist_add_raw(&itl, 0x0016, 4, ip_comp);
-	aim_tlvlist_add_16(&itl, 0x0017, ~pin);
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x0016, 4, ip_comp);
+	aim_tlvlist_add_16(&inner_tlvlist, 0x0017, ~pin);
 
 #if 0
 	/* TODO: If the following is ever enabled, ensure that it is
@@ -1015,9 +1015,9 @@
 	 *       redirect for a file receive (same conditions for
 	 *       sending 0x000f above)
 	 */
-	aim_tlvlist_add_raw(&itl, 0x000e, 2, "en");
-	aim_tlvlist_add_raw(&itl, 0x000d, 8, "us-ascii");
-	aim_tlvlist_add_raw(&itl, 0x000c, 24, "Please accept this file.");
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x000e, 2, "en");
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x000d, 8, "us-ascii");
+	aim_tlvlist_add_raw(&inner_tlvlist, 0x000c, 24, "Please accept this file.");
 #endif
 
 	if (filename != NULL)
@@ -1034,20 +1034,20 @@
 		byte_stream_putstr(&bs, filename);
 		byte_stream_put8(&bs, 0x00);
 
-		aim_tlvlist_add_raw(&itl, 0x2711, bs.len, bs.data);
+		aim_tlvlist_add_raw(&inner_tlvlist, 0x2711, bs.len, bs.data);
 		g_free(bs.data);
 		/* End TLV t(2711) */
 	}
 
-	aim_tlvlist_write(&hdrbs, &itl);
-
-	aim_tlvlist_add_raw(&tl, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
+	aim_tlvlist_write(&hdrbs, &inner_tlvlist);
+
+	aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
 	g_free(hdrbs.data);
 
-	aim_tlvlist_write(&frame->data, &tl);
-
-	aim_tlvlist_free(&itl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &outer_tlvlist);
+
+	aim_tlvlist_free(inner_tlvlist);
+	aim_tlvlist_free(outer_tlvlist);
 
 	flap_connection_send(conn, frame);
 }
@@ -1226,7 +1226,7 @@
 	aim_rxcallback_t userfunc;
 	guchar cookie[8];
 	guint16 channel;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	char *sn;
 	int snlen;
 	guint16 icbmflags = 0;
@@ -1281,7 +1281,7 @@
 
 	g_free(sn);
 	g_free(msg);
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
@@ -1874,11 +1874,11 @@
 
 typedef void (*ch2_args_destructor_t)(OscarData *od, IcbmArgsCh2 *args);
 
-static int incomingim_ch2(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, guint8 *cookie)
+static int incomingim_ch2(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, GSList *tlvlist, guint8 *cookie)
 {
 	aim_rxcallback_t userfunc;
 	aim_tlv_t *block1, *servdatatlv;
-	aim_tlvlist_t *list2;
+	GSList *list2;
 	aim_tlv_t *tlv;
 	IcbmArgsCh2 args;
 	ByteStream bbs, sdbs, *sdbsptr = NULL;
@@ -2078,12 +2078,12 @@
 	g_free((char *)args.encoding);
 	g_free((char *)args.language);
 
-	aim_tlvlist_free(&list2);
+	aim_tlvlist_free(list2);
 
 	return ret;
 }
 
-static int incomingim_ch4(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, guint8 *cookie)
+static int incomingim_ch4(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, GSList *tlvlist, guint8 *cookie)
 {
 	ByteStream meat;
 	aim_rxcallback_t userfunc;
@@ -2186,7 +2186,7 @@
 		ret = incomingim_ch1(od, conn, mod, frame, snac, channel, &userinfo, bs, cookie);
 
 	} else if (channel == 2) {
-		aim_tlvlist_t *tlvlist;
+		GSList *tlvlist;
 
 		/*
 		 * Read block of TLVs (not including the userinfo data).  All
@@ -2196,14 +2196,14 @@
 
 		ret = incomingim_ch2(od, conn, mod, frame, snac, channel, &userinfo, tlvlist, cookie);
 
-		aim_tlvlist_free(&tlvlist);
+		aim_tlvlist_free(tlvlist);
 
 	} else if (channel == 4) {
-		aim_tlvlist_t *tlvlist;
+		GSList *tlvlist;
 
 		tlvlist = aim_tlvlist_read(bs);
 		ret = incomingim_ch4(od, conn, mod, frame, snac, channel, &userinfo, tlvlist, cookie);
-		aim_tlvlist_free(&tlvlist);
+		aim_tlvlist_free(tlvlist);
 
 	} else {
 		purple_debug_misc("oscar", "icbm: ICBM received on an unsupported channel.  Ignoring.  (chan = %04x)\n", channel);
@@ -2284,7 +2284,7 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	if (!od || !(conn = flap_connection_findbygroup(od, 0x0004)))
 		return -EINVAL;
@@ -2300,9 +2300,9 @@
 	byte_stream_put8(&frame->data, strlen(sn));
 	byte_stream_putstr(&frame->data, sn);
 
-	aim_tlvlist_add_16(&tl, 0x0003, code);
-	aim_tlvlist_write(&frame->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_add_16(&tlvlist, 0x0003, code);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
--- a/libpurple/protocols/oscar/family_icq.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/family_icq.c	Mon Jun 18 01:48:35 2007 +0000
@@ -474,14 +474,14 @@
 icqresponse(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
 {
 	int ret = 0;
-	aim_tlvlist_t *tl;
+	GSList *tlvlist;
 	aim_tlv_t *datatlv;
 	ByteStream qbs;
 	guint32 ouruin;
 	guint16 cmdlen, cmd, reqid;
 
-	if (!(tl = aim_tlvlist_read(bs)) || !(datatlv = aim_tlv_gettlv(tl, 0x0001, 1))) {
-		aim_tlvlist_free(&tl);
+	if (!(tlvlist = aim_tlvlist_read(bs)) || !(datatlv = aim_tlv_gettlv(tlvlist, 0x0001, 1))) {
+		aim_tlvlist_free(tlvlist);
 		purple_debug_misc("oscar", "corrupt ICQ response\n");
 		return 0;
 	}
@@ -661,7 +661,7 @@
 		}
 	}
 
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
--- a/libpurple/protocols/oscar/family_locate.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/family_locate.c	Mon Jun 18 01:48:35 2007 +0000
@@ -930,7 +930,7 @@
 int
 aim_putuserinfo(ByteStream *bs, aim_userinfo_t *info)
 {
-	aim_tlvlist_t *tlvlist = NULL;
+	GSList *tlvlist = NULL;
 
 	if (!bs || !info)
 		return -EINVAL;
@@ -965,9 +965,9 @@
 	if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN)
 		aim_tlvlist_add_32(&tlvlist, (guint16)((info->flags & AIM_FLAG_AOL) ? 0x0010 : 0x000f), info->sessionlen);
 
-	byte_stream_put16(bs, aim_tlvlist_count(&tlvlist));
+	byte_stream_put16(bs, aim_tlvlist_count(tlvlist));
 	aim_tlvlist_write(bs, &tlvlist);
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return 0;
 }
@@ -1050,7 +1050,7 @@
 static int
 rights(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
 {
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	aim_rxcallback_t userfunc;
 	int ret = 0;
 	guint16 maxsiglen = 0;
@@ -1063,7 +1063,7 @@
 	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
 		ret = userfunc(od, conn, frame, maxsiglen);
 
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
@@ -1096,7 +1096,7 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 	char *encoding;
 	static const char defencoding[] = {"text/aolrtf; charset=\"%s\""};
 
@@ -1115,8 +1115,8 @@
 		/* no + 1 here because of %s */
 		encoding = g_malloc(strlen(defencoding) + strlen(profile_encoding));
 		snprintf(encoding, strlen(defencoding) + strlen(profile_encoding), defencoding, profile_encoding);
-		aim_tlvlist_add_str(&tl, 0x0001, encoding);
-		aim_tlvlist_add_raw(&tl, 0x0002, profile_len, (const guchar *)profile);
+		aim_tlvlist_add_str(&tlvlist, 0x0001, encoding);
+		aim_tlvlist_add_raw(&tlvlist, 0x0002, profile_len, (const guchar *)profile);
 		g_free(encoding);
 	}
 
@@ -1132,20 +1132,20 @@
 		if (awaymsg_len) {
 			encoding = g_malloc(strlen(defencoding) + strlen(awaymsg_encoding));
 			snprintf(encoding, strlen(defencoding) + strlen(awaymsg_encoding), defencoding, awaymsg_encoding);
-			aim_tlvlist_add_str(&tl, 0x0003, encoding);
-			aim_tlvlist_add_raw(&tl, 0x0004, awaymsg_len, (const guchar *)awaymsg);
+			aim_tlvlist_add_str(&tlvlist, 0x0003, encoding);
+			aim_tlvlist_add_raw(&tlvlist, 0x0004, awaymsg_len, (const guchar *)awaymsg);
 			g_free(encoding);
 		} else
-			aim_tlvlist_add_noval(&tl, 0x0004);
+			aim_tlvlist_add_noval(&tlvlist, 0x0004);
 	}
 
-	frame = flap_frame_new(od, 0x02, 10 + aim_tlvlist_size(&tl));
+	frame = flap_frame_new(od, 0x02, 10 + aim_tlvlist_size(tlvlist));
 
 	snacid = aim_cachesnac(od, 0x0002, 0x0004, 0x0000, NULL, 0);
 	aim_putsnac(&frame->data, 0x0002, 0x004, 0x0000, snacid);
 
-	aim_tlvlist_write(&frame->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -1161,20 +1161,20 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
 		return -EINVAL;
 
-	aim_tlvlist_add_caps(&tl, 0x0005, caps);
+	aim_tlvlist_add_caps(&tlvlist, 0x0005, caps);
 
-	frame = flap_frame_new(od, 0x02, 10 + aim_tlvlist_size(&tl));
+	frame = flap_frame_new(od, 0x02, 10 + aim_tlvlist_size(tlvlist));
 
 	snacid = aim_cachesnac(od, 0x0002, 0x0004, 0x0000, NULL, 0);
 	aim_putsnac(&frame->data, 0x0002, 0x004, 0x0000, snacid);
 
-	aim_tlvlist_write(&frame->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -1221,7 +1221,7 @@
 	int ret = 0;
 	aim_rxcallback_t userfunc;
 	aim_userinfo_t *userinfo, *userinfo2;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	aim_tlv_t *tlv = NULL;
 	int was_explicit;
 
@@ -1252,7 +1252,7 @@
 		userinfo->capabilities = aim_locate_getcaps(od, &cbs, tlv->length);
 		userinfo->present = AIM_USERINFO_PRESENT_CAPABILITIES;
 	}
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	aim_locate_adduserinfo(od, userinfo);
 	userinfo2 = aim_locate_finduserinfo(od, userinfo->sn);
@@ -1284,42 +1284,42 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
 		return -EINVAL;
 
-	aim_tlvlist_add_16(&tl, 0x000a, privacy);
+	aim_tlvlist_add_16(&tlvlist, 0x000a, privacy);
 
 	if (first)
-		aim_tlvlist_add_str(&tl, 0x0001, first);
+		aim_tlvlist_add_str(&tlvlist, 0x0001, first);
 	if (last)
-		aim_tlvlist_add_str(&tl, 0x0002, last);
+		aim_tlvlist_add_str(&tlvlist, 0x0002, last);
 	if (middle)
-		aim_tlvlist_add_str(&tl, 0x0003, middle);
+		aim_tlvlist_add_str(&tlvlist, 0x0003, middle);
 	if (maiden)
-		aim_tlvlist_add_str(&tl, 0x0004, maiden);
+		aim_tlvlist_add_str(&tlvlist, 0x0004, maiden);
 
 	if (state)
-		aim_tlvlist_add_str(&tl, 0x0007, state);
+		aim_tlvlist_add_str(&tlvlist, 0x0007, state);
 	if (city)
-		aim_tlvlist_add_str(&tl, 0x0008, city);
+		aim_tlvlist_add_str(&tlvlist, 0x0008, city);
 
 	if (nickname)
-		aim_tlvlist_add_str(&tl, 0x000c, nickname);
+		aim_tlvlist_add_str(&tlvlist, 0x000c, nickname);
 	if (zip)
-		aim_tlvlist_add_str(&tl, 0x000d, zip);
+		aim_tlvlist_add_str(&tlvlist, 0x000d, zip);
 
 	if (street)
-		aim_tlvlist_add_str(&tl, 0x0021, street);
+		aim_tlvlist_add_str(&tlvlist, 0x0021, street);
 
-	frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(&tl));
+	frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(tlvlist));
 
 	snacid = aim_cachesnac(od, 0x0002, 0x0009, 0x0000, NULL, 0);
 
 	aim_putsnac(&frame->data, 0x0002, 0x0009, 0x0000, snacid);
-	aim_tlvlist_write(&frame->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -1365,32 +1365,32 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
 		return -EINVAL;
 
 	/* ?? privacy ?? */
-	aim_tlvlist_add_16(&tl, 0x000a, privacy);
+	aim_tlvlist_add_16(&tlvlist, 0x000a, privacy);
 
 	if (interest1)
-		aim_tlvlist_add_str(&tl, 0x0000b, interest1);
+		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest1);
 	if (interest2)
-		aim_tlvlist_add_str(&tl, 0x0000b, interest2);
+		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest2);
 	if (interest3)
-		aim_tlvlist_add_str(&tl, 0x0000b, interest3);
+		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest3);
 	if (interest4)
-		aim_tlvlist_add_str(&tl, 0x0000b, interest4);
+		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest4);
 	if (interest5)
-		aim_tlvlist_add_str(&tl, 0x0000b, interest5);
+		aim_tlvlist_add_str(&tlvlist, 0x0000b, interest5);
 
-	frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(&tl));
+	frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(tlvlist));
 
 	snacid = aim_cachesnac(od, 0x0002, 0x000f, 0x0000, NULL, 0);
 
 	aim_putsnac(&frame->data, 0x0002, 0x000f, 0x0000, 0);
-	aim_tlvlist_write(&frame->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
--- a/libpurple/protocols/oscar/family_odir.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/family_odir.c	Mon Jun 18 01:48:35 2007 +0000
@@ -43,22 +43,22 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	if (!od || !(conn = flap_connection_findbygroup(od, 0x000f)) || !region || !email)
 		return -EINVAL;
 
 	/* Create a TLV chain, write it to the outgoing frame, then free the chain */
-	aim_tlvlist_add_str(&tl, 0x001c, region);
-	aim_tlvlist_add_16(&tl, 0x000a, 0x0001); /* Type of search */
-	aim_tlvlist_add_str(&tl, 0x0005, email);
+	aim_tlvlist_add_str(&tlvlist, 0x001c, region);
+	aim_tlvlist_add_16(&tlvlist, 0x000a, 0x0001); /* Type of search */
+	aim_tlvlist_add_str(&tlvlist, 0x0005, email);
 
-	frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(&tl));
+	frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(tlvlist));
 	snacid = aim_cachesnac(od, 0x000f, 0x0002, 0x0000, NULL, 0);
 	aim_putsnac(&frame->data, 0x000f, 0x0002, 0x0000, snacid);
 
-	aim_tlvlist_write(&frame->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -91,41 +91,41 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	if (!od || !(conn = flap_connection_findbygroup(od, 0x000f)) || !region)
 		return -EINVAL;
 
 	/* Create a TLV chain, write it to the outgoing frame, then free the chain */
-	aim_tlvlist_add_str(&tl, 0x001c, region);
-	aim_tlvlist_add_16(&tl, 0x000a, 0x0000); /* Type of search */
+	aim_tlvlist_add_str(&tlvlist, 0x001c, region);
+	aim_tlvlist_add_16(&tlvlist, 0x000a, 0x0000); /* Type of search */
 	if (first)
-		aim_tlvlist_add_str(&tl, 0x0001, first);
+		aim_tlvlist_add_str(&tlvlist, 0x0001, first);
 	if (last)
-		aim_tlvlist_add_str(&tl, 0x0002, last);
+		aim_tlvlist_add_str(&tlvlist, 0x0002, last);
 	if (middle)
-		aim_tlvlist_add_str(&tl, 0x0003, middle);
+		aim_tlvlist_add_str(&tlvlist, 0x0003, middle);
 	if (maiden)
-		aim_tlvlist_add_str(&tl, 0x0004, maiden);
+		aim_tlvlist_add_str(&tlvlist, 0x0004, maiden);
 	if (country)
-		aim_tlvlist_add_str(&tl, 0x0006, country);
+		aim_tlvlist_add_str(&tlvlist, 0x0006, country);
 	if (state)
-		aim_tlvlist_add_str(&tl, 0x0007, state);
+		aim_tlvlist_add_str(&tlvlist, 0x0007, state);
 	if (city)
-		aim_tlvlist_add_str(&tl, 0x0008, city);
+		aim_tlvlist_add_str(&tlvlist, 0x0008, city);
 	if (nick)
-		aim_tlvlist_add_str(&tl, 0x000c, nick);
+		aim_tlvlist_add_str(&tlvlist, 0x000c, nick);
 	if (zip)
-		aim_tlvlist_add_str(&tl, 0x000d, zip);
+		aim_tlvlist_add_str(&tlvlist, 0x000d, zip);
 	if (address)
-		aim_tlvlist_add_str(&tl, 0x0021, address);
+		aim_tlvlist_add_str(&tlvlist, 0x0021, address);
 
-	frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(&tl));
+	frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(tlvlist));
 	snacid = aim_cachesnac(od, 0x000f, 0x0002, 0x0000, NULL, 0);
 	aim_putsnac(&frame->data, 0x000f, 0x0002, 0x0000, snacid);
 
-	aim_tlvlist_write(&frame->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -145,23 +145,23 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	if (!od || !(conn = flap_connection_findbygroup(od, 0x000f)) || !region)
 		return -EINVAL;
 
 	/* Create a TLV chain, write it to the outgoing frame, then free the chain */
-	aim_tlvlist_add_str(&tl, 0x001c, region);
-	aim_tlvlist_add_16(&tl, 0x000a, 0x0001); /* Type of search */
+	aim_tlvlist_add_str(&tlvlist, 0x001c, region);
+	aim_tlvlist_add_16(&tlvlist, 0x000a, 0x0001); /* Type of search */
 	if (interest)
-		aim_tlvlist_add_str(&tl, 0x0001, interest);
+		aim_tlvlist_add_str(&tlvlist, 0x0001, interest);
 
-	frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(&tl));
+	frame = flap_frame_new(od, 0x02, 10+aim_tlvlist_size(tlvlist));
 	snacid = aim_cachesnac(od, 0x000f, 0x0002, 0x0000, NULL, 0);
 	aim_putsnac(&frame->data, 0x000f, 0x0002, 0x0000, snacid);
 
-	aim_tlvlist_write(&frame->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -189,22 +189,22 @@
 	/* Allocate a linked list, 1 node per result */
 	while (numresults) {
 		struct aim_odir *new;
-		aim_tlvlist_t *tl = aim_tlvlist_readnum(bs, byte_stream_get16(bs));
+		GSList *tlvlist = aim_tlvlist_readnum(bs, byte_stream_get16(bs));
 		new = (struct aim_odir *)g_malloc(sizeof(struct aim_odir));
-		new->first = aim_tlv_getstr(tl, 0x0001, 1);
-		new->last = aim_tlv_getstr(tl, 0x0002, 1);
-		new->middle = aim_tlv_getstr(tl, 0x0003, 1);
-		new->maiden = aim_tlv_getstr(tl, 0x0004, 1);
-		new->email = aim_tlv_getstr(tl, 0x0005, 1);
-		new->country = aim_tlv_getstr(tl, 0x0006, 1);
-		new->state = aim_tlv_getstr(tl, 0x0007, 1);
-		new->city = aim_tlv_getstr(tl, 0x0008, 1);
-		new->sn = aim_tlv_getstr(tl, 0x0009, 1);
-		new->interest = aim_tlv_getstr(tl, 0x000b, 1);
-		new->nick = aim_tlv_getstr(tl, 0x000c, 1);
-		new->zip = aim_tlv_getstr(tl, 0x000d, 1);
-		new->region = aim_tlv_getstr(tl, 0x001c, 1);
-		new->address = aim_tlv_getstr(tl, 0x0021, 1);
+		new->first = aim_tlv_getstr(tlvlist, 0x0001, 1);
+		new->last = aim_tlv_getstr(tlvlist, 0x0002, 1);
+		new->middle = aim_tlv_getstr(tlvlist, 0x0003, 1);
+		new->maiden = aim_tlv_getstr(tlvlist, 0x0004, 1);
+		new->email = aim_tlv_getstr(tlvlist, 0x0005, 1);
+		new->country = aim_tlv_getstr(tlvlist, 0x0006, 1);
+		new->state = aim_tlv_getstr(tlvlist, 0x0007, 1);
+		new->city = aim_tlv_getstr(tlvlist, 0x0008, 1);
+		new->sn = aim_tlv_getstr(tlvlist, 0x0009, 1);
+		new->interest = aim_tlv_getstr(tlvlist, 0x000b, 1);
+		new->nick = aim_tlv_getstr(tlvlist, 0x000c, 1);
+		new->zip = aim_tlv_getstr(tlvlist, 0x000d, 1);
+		new->region = aim_tlv_getstr(tlvlist, 0x001c, 1);
+		new->address = aim_tlv_getstr(tlvlist, 0x0021, 1);
 		new->next = results;
 		results = new;
 		numresults--;
--- a/libpurple/protocols/oscar/family_oservice.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/family_oservice.c	Mon Jun 18 01:48:35 2007 +0000
@@ -123,7 +123,7 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 	struct chatsnacinfo csi;
 
 	conn = flap_connection_findbygroup(od, SNAC_FAMILY_BOS);
@@ -145,9 +145,9 @@
 	 */
 	byte_stream_put16(&frame->data, 0x000e);
 
-	aim_tlvlist_add_chatroom(&tl, 0x0001, exchange, roomname, instance);
-	aim_tlvlist_write(&frame->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_add_chatroom(&tlvlist, 0x0001, exchange, roomname, instance);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -160,7 +160,7 @@
 {
 	struct aim_redirect_data redir;
 	aim_rxcallback_t userfunc;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	aim_snac_t *origsnac = NULL;
 	int ret = 0;
 
@@ -171,7 +171,7 @@
 	if (!aim_tlv_gettlv(tlvlist, 0x000d, 1) ||
 			!aim_tlv_gettlv(tlvlist, 0x0005, 1) ||
 			!aim_tlv_gettlv(tlvlist, 0x0006, 1)) {
-		aim_tlvlist_free(&tlvlist);
+		aim_tlvlist_free(tlvlist);
 		return 0;
 	}
 
@@ -201,7 +201,7 @@
 		g_free(origsnac->data);
 	g_free(origsnac);
 
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
@@ -606,7 +606,7 @@
 	aim_rxcallback_t userfunc;
 	int ret = 0;
 	guint16 groupcount, i;
-	aim_tlvlist_t *tl;
+	GSList *tlvlist;
 	char *ip = NULL;
 	aim_tlv_t *cktlv;
 
@@ -630,17 +630,17 @@
 		purple_debug_misc("oscar", "bifurcated migration unsupported -- group 0x%04x\n", group);
 	}
 
-	tl = aim_tlvlist_read(bs);
+	tlvlist = aim_tlvlist_read(bs);
 
-	if (aim_tlv_gettlv(tl, 0x0005, 1))
-		ip = aim_tlv_getstr(tl, 0x0005, 1);
+	if (aim_tlv_gettlv(tlvlist, 0x0005, 1))
+		ip = aim_tlv_getstr(tlvlist, 0x0005, 1);
 
-	cktlv = aim_tlv_gettlv(tl, 0x0006, 1);
+	cktlv = aim_tlv_gettlv(tlvlist, 0x0006, 1);
 
 	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
 		ret = userfunc(od, conn, frame, ip, cktlv ? cktlv->value : NULL);
 
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_free(tlvlist);
 	g_free(ip);
 
 	return ret;
@@ -653,7 +653,7 @@
 	aim_rxcallback_t userfunc;
 	char *msg = NULL;
 	int ret = 0;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	guint16 id;
 
 	/*
@@ -681,7 +681,7 @@
 
 	g_free(msg);
 
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
@@ -805,24 +805,24 @@
 	FlapConnection *conn;
 	FlapFrame *frame;
 	aim_snacid_t snacid;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
 		return -EINVAL;
 
 	if (seticqstatus)
 	{
-		aim_tlvlist_add_32(&tl, 0x0006, icqstatus |
+		aim_tlvlist_add_32(&tlvlist, 0x0006, icqstatus |
 				AIM_ICQ_STATE_HIDEIP | AIM_ICQ_STATE_DIRECTREQUIREAUTH);
 	}
 
 #if 0
 	if (other_stuff_that_isnt_implemented)
 	{
-		aim_tlvlist_add_raw(&tl, 0x000c, 0x0025,
+		aim_tlvlist_add_raw(&tlvlist, 0x000c, 0x0025,
 				chunk_of_x25_bytes_with_ip_address_etc);
-		aim_tlvlist_add_raw(&tl, 0x0011, 0x0005, unknown 0x01 61 10 f6 41);
-		aim_tlvlist_add_16(&tl, 0x0012, unknown 0x00 00);
+		aim_tlvlist_add_raw(&tlvlist, 0x0011, 0x0005, unknown 0x01 61 10 f6 41);
+		aim_tlvlist_add_16(&tlvlist, 0x0012, unknown 0x00 00);
 	}
 #endif
 
@@ -851,18 +851,18 @@
 			byte_stream_putstr(&tmpbs, itmsurl);
 		byte_stream_put16(&tmpbs, 0x0000);
 
-		aim_tlvlist_add_raw(&tl, 0x001d,
+		aim_tlvlist_add_raw(&tlvlist, 0x001d,
 				byte_stream_curpos(&tmpbs), tmpbs.data);
 		g_free(tmpbs.data);
 	}
 
-	frame = flap_frame_new(od, 0x02, 10 + aim_tlvlist_size(&tl));
+	frame = flap_frame_new(od, 0x02, 10 + aim_tlvlist_size(tlvlist));
 
 	snacid = aim_cachesnac(od, 0x0001, 0x001e, 0x0000, NULL, 0);
 	aim_putsnac(&frame->data, 0x0001, 0x001e, 0x0000, snacid);
 
-	aim_tlvlist_write(&frame->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 
@@ -913,14 +913,14 @@
 	int ret = 0;
 	aim_rxcallback_t userfunc;
 	guint32 offset, len;
-	aim_tlvlist_t *list;
+	GSList *tlvlist;
 	char *modname;
 
 	offset = byte_stream_get32(bs);
 	len = byte_stream_get32(bs);
-	list = aim_tlvlist_read(bs);
+	tlvlist = aim_tlvlist_read(bs);
 
-	modname = aim_tlv_getstr(list, 0x0001, 1);
+	modname = aim_tlv_getstr(tlvlist, 0x0001, 1);
 
 	purple_debug_info("oscar", "Got memory request for data at 0x%08lx (%d bytes) of requested %s\n", offset, len, modname ? modname : "aim.exe");
 
@@ -928,7 +928,7 @@
 		ret = userfunc(od, conn, frame, offset, len, modname);
 
 	g_free(modname);
-	aim_tlvlist_free(&list);
+	aim_tlvlist_free(tlvlist);
 
 	return ret;
 }
--- a/libpurple/protocols/oscar/family_popup.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/family_popup.c	Mon Jun 18 01:48:35 2007 +0000
@@ -37,23 +37,23 @@
 parsepopup(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
 {
 	aim_rxcallback_t userfunc;
-	aim_tlvlist_t *tl;
+	GSList *tlvlist;
 	int ret = 0;
 	char *msg, *url;
 	guint16 width, height, delay;
 
-	tl = aim_tlvlist_read(bs);
+	tlvlist = aim_tlvlist_read(bs);
 
-	msg = aim_tlv_getstr(tl, 0x0001, 1);
-	url = aim_tlv_getstr(tl, 0x0002, 1);
-	width = aim_tlv_get16(tl, 0x0003, 1);
-	height = aim_tlv_get16(tl, 0x0004, 1);
-	delay = aim_tlv_get16(tl, 0x0005, 1);
+	msg = aim_tlv_getstr(tlvlist, 0x0001, 1);
+	url = aim_tlv_getstr(tlvlist, 0x0002, 1);
+	width = aim_tlv_get16(tlvlist, 0x0003, 1);
+	height = aim_tlv_get16(tlvlist, 0x0004, 1);
+	delay = aim_tlv_get16(tlvlist, 0x0005, 1);
 
 	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
 		ret = userfunc(od, conn, frame, msg, url, width, height, delay);
 
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_free(tlvlist);
 	g_free(msg);
 	g_free(url);
 
--- a/libpurple/protocols/oscar/family_userlookup.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/family_userlookup.c	Mon Jun 18 01:48:35 2007 +0000
@@ -89,7 +89,7 @@
 static int reply(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
 {
 	int j = 0, m, ret = 0;
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	char *cur = NULL, *buf = NULL;
 	aim_rxcallback_t userfunc;
 	aim_snac_t *snac2;
@@ -99,7 +99,7 @@
 		searchaddr = (const char *)snac2->data;
 
 	tlvlist = aim_tlvlist_read(bs);
-	m = aim_tlvlist_count(&tlvlist);
+	m = aim_tlvlist_count(tlvlist);
 
 	/* XXX uhm.
 	 * This is the only place that uses something other than 1 for the 3rd
@@ -116,7 +116,7 @@
 	}
 	g_free(cur);
 
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
 		ret = userfunc(od, conn, frame, searchaddr, j, buf);
--- a/libpurple/protocols/oscar/flap_connection.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/flap_connection.c	Mon Jun 18 01:48:35 2007 +0000
@@ -61,13 +61,13 @@
 flap_connection_send_version_with_cookie(OscarData *od, FlapConnection *conn, guint16 length, const guint8 *chipsahoy)
 {
 	FlapFrame *frame;
-	aim_tlvlist_t *tl = NULL;
+	GSList *tlvlist = NULL;
 
 	frame = flap_frame_new(od, 0x01, 4 + 2 + 2 + length);
 	byte_stream_put32(&frame->data, 0x00000001);
-	aim_tlvlist_add_raw(&tl, 0x0006, length, chipsahoy);
-	aim_tlvlist_write(&frame->data, &tl);
-	aim_tlvlist_free(&tl);
+	aim_tlvlist_add_raw(&tlvlist, 0x0006, length, chipsahoy);
+	aim_tlvlist_write(&frame->data, &tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	flap_connection_send(conn, frame);
 }
@@ -303,7 +303,7 @@
 		}
 	}
 
-	if (conn->fd != -1)
+	if (conn->fd >= 0)
 	{
 		if (conn->type == SNAC_FAMILY_LOCATE)
 			flap_connection_send_close(od, conn);
@@ -693,7 +693,7 @@
 static void
 parse_flap_ch4(OscarData *od, FlapConnection *conn, FlapFrame *frame)
 {
-	aim_tlvlist_t *tlvlist;
+	GSList *tlvlist;
 	char *msg = NULL;
 	guint16 code = 0;
 	aim_rxcallback_t userfunc;
@@ -721,7 +721,7 @@
 	if ((userfunc = aim_callhandler(od, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR)))
 		userfunc(od, conn, frame, code, msg);
 
-	aim_tlvlist_free(&tlvlist);
+	aim_tlvlist_free(tlvlist);
 
 	g_free(msg);
 }
@@ -792,7 +792,7 @@
 			}
 
 			/* If there was an error then close the connection */
-			if (read == -1)
+			if (read < 0)
 			{
 				if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
 					/* No worries */
@@ -853,7 +853,7 @@
 				break;
 			}
 
-			if (read == -1)
+			if (read < 0)
 			{
 				if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
 					/* No worries */
@@ -902,7 +902,7 @@
 	ret = send(conn->fd, conn->buffer_outgoing->outptr, writelen, 0);
 	if (ret <= 0)
 	{
-		if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
+		if (ret < 0 && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
 			/* No worries */
 			return;
 
@@ -936,7 +936,7 @@
 	purple_circ_buffer_append(conn->buffer_outgoing, bs->data, count);
 
 	/* If we haven't already started writing stuff, then start the cycle */
-	if ((conn->watcher_outgoing == 0) && (conn->fd != -1))
+	if ((conn->watcher_outgoing == 0) && (conn->fd >= 0))
 	{
 		conn->watcher_outgoing = purple_input_add(conn->fd,
 				PURPLE_INPUT_WRITE, send_cb, conn);
--- a/libpurple/protocols/oscar/odc.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/odc.c	Mon Jun 18 01:48:35 2007 +0000
@@ -447,7 +447,7 @@
 		return;
 	}
 
-	if (read == -1)
+	if (read < 0)
 	{
 		if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
 			/* No worries */
--- a/libpurple/protocols/oscar/oscar.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Mon Jun 18 01:48:35 2007 +0000
@@ -298,7 +298,7 @@
 }
 
 gchar *
-oscar_encoding_to_utf8(const char *encoding, const char *text, int textlen)
+oscar_encoding_to_utf8(PurpleAccount *account, const char *encoding, const char *text, int textlen)
 {
 	gchar *utf8 = NULL;
 
@@ -311,7 +311,25 @@
 	{
 		utf8 = g_convert(text, textlen, "UTF-8", "Windows-1252", NULL, NULL, NULL);
 	} else if (!g_ascii_strcasecmp(encoding, "unicode-2-0")) {
-		utf8 = g_convert(text, textlen, "UTF-8", "UCS-2BE", NULL, NULL, NULL);
+		/* Some official ICQ clients are apparently total crack,
+		 * and have been known to save a UTF-8 string converted
+		 * from the locale character set to UCS-2 (not from UTF-8
+		 * to UCS-2!) in the away message.  This hack should find
+		 * and do something (un)reasonable with that, and not
+		 * mess up too much else. */
+		const gchar *charset = purple_account_get_string(account, "encoding", NULL);
+		if (charset) {
+			gsize len;
+			utf8 = g_convert(text, textlen, charset, "UCS-2BE", &len, NULL, NULL);
+			if (!utf8 || len != textlen || !g_utf8_validate(utf8, -1, NULL)) {
+				g_free(utf8);
+				utf8 = NULL;
+			} else {
+				purple_debug_info("oscar", "Used broken ICQ fallback encoding\n");
+			}
+		}
+		if (!utf8)
+			utf8 = g_convert(text, textlen, "UTF-8", "UCS-2BE", NULL, NULL, NULL);
 	} else if (g_ascii_strcasecmp(encoding, "utf-8")) {
 		purple_debug_warning("oscar", "Unrecognized character encoding \"%s\", "
 						   "attempting to convert to UTF-8 anyway\n", encoding);
@@ -1604,8 +1622,7 @@
 			straight_to_hell, pos) == NULL)
 	{
 		char buf[256];
-		if (pos->modname)
-			g_free(pos->modname);
+		g_free(pos->modname);
 		g_free(pos);
 		g_snprintf(buf, sizeof(buf), _("You may be disconnected shortly.  "
 			"Check %s for updates."), PURPLE_WEBSITE);
@@ -1775,7 +1792,7 @@
 	{
 		have_status_message = TRUE;
 		if (info->status[0] != '\0')
-			message = oscar_encoding_to_utf8(info->status_encoding,
+			message = oscar_encoding_to_utf8(account, info->status_encoding,
 											 info->status, info->status_len);
 	}
 
@@ -1791,7 +1808,7 @@
 		if ((status_id == OSCAR_STATUS_ID_AVAILABLE) && (info->itmsurl != NULL))
 		{
 			char *itmsurl;
-			itmsurl = oscar_encoding_to_utf8(info->itmsurl_encoding,
+			itmsurl = oscar_encoding_to_utf8(account, info->itmsurl_encoding,
 					info->itmsurl, info->itmsurl_len);
 			purple_prpl_got_user_status(account, info->sn, status_id,
 					"message", message, "itmsurl", itmsurl, NULL);
@@ -1826,9 +1843,8 @@
 		signon = time(NULL) - info->sessionlen;
 	if (!aim_sncmp(purple_account_get_username(account), info->sn)) {
 		purple_connection_set_display_name(gc, info->sn);
-		od->timeoffset = signon - purple_presence_get_login_time(presence);
-	}
-	purple_prpl_got_user_login_time(account, info->sn, signon - od->timeoffset);
+	}
+	purple_prpl_got_user_login_time(account, info->sn, signon);
 
 	/* Idle time stuff */
 	/* info->idletime is the number of minutes that this user has been idle */
@@ -2049,7 +2065,8 @@
 		{
 			char *encoding = NULL;
 			encoding = oscar_encoding_extract(args->encoding);
-			message = oscar_encoding_to_utf8(encoding, args->msg, args->msglen);
+			message = oscar_encoding_to_utf8(account, encoding, args->msg,
+			                                 args->msglen);
 			g_free(encoding);
 		} else {
 			if (g_utf8_validate(args->msg, args->msglen, NULL))
@@ -2067,7 +2084,7 @@
 			return 1;
 		}
 		encoding = args->encoding ? oscar_encoding_extract(args->encoding) : NULL;
-		utf8name = oscar_encoding_to_utf8(encoding,
+		utf8name = oscar_encoding_to_utf8(account, encoding,
 				args->info.chat.roominfo.name,
 				args->info.chat.roominfo.namelen);
 		g_free(encoding);
@@ -2202,7 +2219,7 @@
 				   buddy->name, group->name);
 		aim_ssi_sendauthrequest(od, data->name, msg ? msg : _("Please authorize me so I can add you to my buddy list."));
 		if (!aim_ssi_itemlist_finditem(od->ssi.local, group->name, buddy->name, AIM_SSI_TYPE_BUDDY))
-			aim_ssi_addbuddy(od, buddy->name, group->name, purple_buddy_get_alias_only(buddy), NULL, NULL, 1);
+			aim_ssi_addbuddy(od, buddy->name, group->name, NULL, purple_buddy_get_alias_only(buddy), NULL, NULL, TRUE);
 	}
 }
 
@@ -2850,12 +2867,12 @@
 	g_free(tmp);
 
 	if (userinfo->present & AIM_USERINFO_PRESENT_ONLINESINCE) {
-		time_t t = userinfo->onlinesince - od->timeoffset;
+		time_t t = userinfo->onlinesince;
 		oscar_user_info_add_pair(user_info, _("Online Since"), purple_date_format_full(localtime(&t)));
 	}
 
 	if (userinfo->present & AIM_USERINFO_PRESENT_MEMBERSINCE) {
-		time_t t = userinfo->membersince - od->timeoffset;
+		time_t t = userinfo->membersince;
 		oscar_user_info_add_pair(user_info, _("Member Since"), purple_date_format_full(localtime(&t)));
 	}
 
@@ -2877,12 +2894,12 @@
 	if ((userinfo->status != NULL) && !(userinfo->flags & AIM_FLAG_AWAY))
 	{
 		if (userinfo->status[0] != '\0')
-			tmp = oscar_encoding_to_utf8(userinfo->status_encoding,
+			tmp = oscar_encoding_to_utf8(account, userinfo->status_encoding,
 											 userinfo->status, userinfo->status_len);
 #if defined (_WIN32) || defined (__APPLE__)
 		if (userinfo->itmsurl && (userinfo->itmsurl[0] != '\0')) {
 			gchar *itmsurl, *tmp2;
-			itmsurl = oscar_encoding_to_utf8(userinfo->itmsurl_encoding,
+			itmsurl = oscar_encoding_to_utf8(account, userinfo->itmsurl_encoding,
 					userinfo->itmsurl, userinfo->itmsurl_len);
 			tmp2 = g_strdup_printf("<a href=\"%s\">%s</a>",
 					itmsurl, tmp);
@@ -2898,7 +2915,8 @@
 	/* Away message */
 	if ((userinfo->flags & AIM_FLAG_AWAY) && (userinfo->away_len > 0) && (userinfo->away != NULL) && (userinfo->away_encoding != NULL)) {
 		tmp = oscar_encoding_extract(userinfo->away_encoding);
-		away_utf8 = oscar_encoding_to_utf8(tmp, userinfo->away, userinfo->away_len);
+		away_utf8 = oscar_encoding_to_utf8(account, tmp, userinfo->away,
+		                                   userinfo->away_len);
 		g_free(tmp);
 		if (away_utf8 != NULL) {
 			tmp = purple_str_sub_away_formatters(away_utf8, purple_account_get_username(account));
@@ -2912,7 +2930,8 @@
 	/* Info */
 	if ((userinfo->info_len > 0) && (userinfo->info != NULL) && (userinfo->info_encoding != NULL)) {
 		tmp = oscar_encoding_extract(userinfo->info_encoding);
-		info_utf8 = oscar_encoding_to_utf8(tmp, userinfo->info, userinfo->info_len);
+		info_utf8 = oscar_encoding_to_utf8(account, tmp, userinfo->info,
+		                                   userinfo->info_len);
 		g_free(tmp);
 		if (info_utf8 != NULL) {
 			tmp = purple_str_sub_away_formatters(info_utf8, purple_account_get_username(account));
@@ -2932,6 +2951,7 @@
 static int purple_got_infoblock(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
 {
 	PurpleConnection *gc = od->gc;
+	PurpleAccount *account = purple_connection_get_account(gc);
 	PurpleBuddy *b;
 	PurplePresence *presence;
 	PurpleStatus *status;
@@ -2944,7 +2964,7 @@
 	userinfo = va_arg(ap, aim_userinfo_t *);
 	va_end(ap);
 
-	b = purple_find_buddy(purple_connection_get_account(gc), userinfo->sn);
+	b = purple_find_buddy(account, userinfo->sn);
 	if (b == NULL)
 		return 1;
 
@@ -2964,7 +2984,9 @@
 		if ((userinfo->flags & AIM_FLAG_AWAY) &&
 			(userinfo->away_len > 0) && (userinfo->away != NULL) && (userinfo->away_encoding != NULL)) {
 			gchar *charset = oscar_encoding_extract(userinfo->away_encoding);
-			message = oscar_encoding_to_utf8(charset, userinfo->away, userinfo->away_len);
+			message = oscar_encoding_to_utf8(account, charset,
+			                                 userinfo->away,
+			                                 userinfo->away_len);
 			g_free(charset);
 			purple_status_set_attr_string(status, "message", message);
 			g_free(message);
@@ -3160,6 +3182,7 @@
 
 static int purple_conv_chat_incoming_msg(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
 	PurpleConnection *gc = od->gc;
+	PurpleAccount *account = purple_connection_get_account(gc);
 	struct chat_connection *ccon = find_oscar_chat_by_conn(gc, conn);
 	gchar *utf8;
 	va_list ap;
@@ -3178,7 +3201,7 @@
 	charset = va_arg(ap, char *);
 	va_end(ap);
 
-	utf8 = oscar_encoding_to_utf8(charset, msg, len);
+	utf8 = oscar_encoding_to_utf8(account, charset, msg, len);
 	if (utf8 == NULL)
 		/* The conversion failed! */
 		utf8 = g_strdup(_("[Unable to display a message from this user because it contained invalid characters.]"));
@@ -4168,6 +4191,7 @@
 	PeerConnection *conn;
 	int ret;
 	char *tmp1, *tmp2;
+	gboolean is_html;
 
 	od = (OscarData *)gc->proto_data;
 	account = purple_connection_get_account(gc);
@@ -4186,7 +4210,6 @@
 	} else {
 		struct buddyinfo *bi;
 		struct aim_sendimext_args args;
-		gsize len;
 		PurpleConversation *conv;
 		PurpleStoredImage *img;
 
@@ -4277,22 +4300,43 @@
 		if (aim_sn_is_sms(name)) {
 			/* Messaging an SMS (mobile) user */
 			tmp2 = purple_markup_strip_html(tmp1);
+			is_html = FALSE;
 		} else if (aim_sn_is_icq(purple_account_get_username(account))) {
-			if (aim_sn_is_icq(name))
+			if (aim_sn_is_icq(name)) {
 				/* From ICQ to ICQ */
 				tmp2 = purple_markup_strip_html(tmp1);
-			else
+				is_html = FALSE;
+			} else {
 				/* From ICQ to AIM */
 				tmp2 = g_strdup(tmp1);
+				is_html = TRUE;
+			}
 		} else {
 			/* From AIM to AIM and AIM to ICQ */
 			tmp2 = g_strdup(tmp1);
+			is_html = TRUE;
 		}
 		g_free(tmp1);
 		tmp1 = tmp2;
-		len = strlen(tmp1);
 
 		purple_plugin_oscar_convert_to_best_encoding(gc, name, tmp1, (char **)&args.msg, &args.msglen, &args.charset, &args.charsubset);
+		if (is_html && (args.msglen > MAXMSGLEN)) {
+			/* If the length was too long, try stripping the HTML and then running it back through
+			* purple_strdup_withhtml() and the encoding process. The result may be shorter. */
+			g_free((char *)args.msg);
+			
+			tmp2 = purple_markup_strip_html(tmp1);
+			g_free(tmp1);
+			
+			tmp1 = purple_strdup_withhtml(tmp2);
+			g_free(tmp2);
+			
+			purple_plugin_oscar_convert_to_best_encoding(gc, name, tmp1, (char **)&args.msg, &args.msglen, &args.charset, &args.charsubset);
+
+			purple_debug_info("oscar", "Sending %s as %s because the original was too long.",
+								  message, (char *)args.msg);
+		}
+
 		purple_debug_info("oscar", "Sending IM, charset=0x%04hx, charsubset=0x%04hx, length=%d\n",
 						args.charset, args.charsubset, args.msglen);
 		ret = aim_im_sendch1_ext(od, &args);
@@ -4387,7 +4431,7 @@
 	if (purple_account_get_bool(account, "web_aware", OSCAR_DEFAULT_WEB_AWARE))
 		data |= AIM_ICQ_STATE_WEBAWARE;
 
-	if (!strcmp(status_id, OSCAR_STATUS_ID_AVAILABLE) || !strcmp(status_id, OSCAR_STATUS_ID_AVAILABLE))
+	if (!strcmp(status_id, OSCAR_STATUS_ID_AVAILABLE))
 		data |= AIM_ICQ_STATE_NORMAL;
 	else if (!strcmp(status_id, OSCAR_STATUS_ID_AWAY))
 		data |= AIM_ICQ_STATE_AWAY;
@@ -4592,7 +4636,7 @@
 	if ((od->ssi.received_data) && !(aim_ssi_itemlist_finditem(od->ssi.local, group->name, buddy->name, AIM_SSI_TYPE_BUDDY))) {
 		purple_debug_info("oscar",
 				   "ssi: adding buddy %s to group %s\n", buddy->name, group->name);
-		aim_ssi_addbuddy(od, buddy->name, group->name, purple_buddy_get_alias_only(buddy), NULL, NULL, 0);
+		aim_ssi_addbuddy(od, buddy->name, group->name, NULL, purple_buddy_get_alias_only(buddy), NULL, NULL, 0);
 	}
 
 	/* XXX - Should this be done from AIM accounts, as well? */
@@ -5324,7 +5368,7 @@
 	OscarData *od = (OscarData *)gc->proto_data;
 	PurpleConversation *conv = NULL;
 	struct chat_connection *c = NULL;
-	char *buf, *buf2;
+	char *buf, *buf2, *buf3;
 	guint16 charset, charsubset;
 	char *charsetstr = NULL;
 	int len;
@@ -5336,7 +5380,6 @@
 		return -EINVAL;
 
 	buf = purple_strdup_withhtml(message);
-	len = strlen(buf);
 
 	if (strstr(buf, "<IMG "))
 		purple_conversation_write(conv, "",
@@ -5350,8 +5393,28 @@
 	 * visible characters" and not "number of bytes"
 	 */
 	if ((len > c->maxlen) || (len > c->maxvis)) {
+		/* If the length was too long, try stripping the HTML and then running it back through
+		 * purple_strdup_withhtml() and the encoding process. The result may be shorter. */
 		g_free(buf2);
-		return -E2BIG;
+
+		buf3 = purple_markup_strip_html(buf);
+		g_free(buf);
+
+		buf = purple_strdup_withhtml(buf3);
+		g_free(buf3);
+
+		purple_plugin_oscar_convert_to_best_encoding(gc, NULL, buf, &buf2, &len, &charset, &charsubset);
+
+		if ((len > c->maxlen) || (len > c->maxvis)) {
+			purple_debug_warning("oscar", "Could not send %s because (%i > maxlen %i) or (%i > maxvis %i)",
+					buf2, len, c->maxlen, len, c->maxvis);
+			g_free(buf);
+			g_free(buf2);
+			return -E2BIG;
+		}
+
+		purple_debug_info("oscar", "Sending %s as %s because the original was too long.",
+				message, buf2);
 	}
 
 	if (charset == AIM_CHARSET_ASCII)
@@ -5362,6 +5425,7 @@
 		charsetstr = "iso-8859-1";
 	aim_chat_send_im(od, c->conn, 0, buf2, len, charsetstr, "en");
 	g_free(buf2);
+	g_free(buf);
 
 	return 0;
 }
--- a/libpurple/protocols/oscar/oscar.h	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/oscar.h	Mon Jun 18 01:48:35 2007 +0000
@@ -447,7 +447,6 @@
 	guint icontimer;
 	guint getblisttimer;
 	guint getinfotimer;
-	gint timeoffset;
 
 	struct {
 		guint maxwatchers; /* max users who can watch you */
@@ -935,7 +934,7 @@
 /* 0x0014 */ int aim_im_sendmtn(OscarData *od, guint16 type1, const char *sn, guint16 type2);
 void aim_icbm_makecookie(guchar* cookie);
 gchar *oscar_encoding_extract(const char *encoding);
-gchar *oscar_encoding_to_utf8(const char *encoding, const char *text, int textlen);
+gchar *oscar_encoding_to_utf8(PurpleAccount *account, const char *encoding, const char *text, int textlen);
 gchar *purple_plugin_oscar_decode_im_part(PurpleAccount *account, const char *sourcesn, guint16 charset, guint16 charsubset, const gchar *data, gsize datalen);
 
 
@@ -1172,7 +1171,7 @@
 	guint16 gid;
 	guint16 bid;
 	guint16 type;
-	struct aim_tlvlist_s *data;
+	GSList *data;
 	struct aim_ssi_item *next;
 };
 
@@ -1208,7 +1207,7 @@
 gboolean aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *sn);
 
 /* Client functions for changing SSI data */
-int aim_ssi_addbuddy(OscarData *od, const char *name, const char *group, const char *alias, const char *comment, const char *smsnum, int needauth);
+int aim_ssi_addbuddy(OscarData *od, const char *name, const char *group, GSList *tlvlist, const char *alias, const char *comment, const char *smsnum, gboolean needauth);
 int aim_ssi_addpermit(OscarData *od, const char *name);
 int aim_ssi_adddeny(OscarData *od, const char *name);
 int aim_ssi_delbuddy(OscarData *od, const char *name, const char *group);
@@ -1357,54 +1356,47 @@
 	guint8 *value;
 } aim_tlv_t;
 
-/* TLV List structure */
-typedef struct aim_tlvlist_s
-{
-	aim_tlv_t *tlv;
-	struct aim_tlvlist_s *next;
-} aim_tlvlist_t;
-
 /* TLV handling functions */
 char *aim_tlv_getvalue_as_string(aim_tlv_t *tlv);
 
-aim_tlv_t *aim_tlv_gettlv(aim_tlvlist_t *list, guint16 type, const int nth);
-int aim_tlv_getlength(aim_tlvlist_t *list, guint16 type, const int nth);
-char *aim_tlv_getstr(aim_tlvlist_t *list, const guint16 type, const int nth);
-guint8 aim_tlv_get8(aim_tlvlist_t *list, const guint16 type, const int nth);
-guint16 aim_tlv_get16(aim_tlvlist_t *list, const guint16 type, const int nth);
-guint32 aim_tlv_get32(aim_tlvlist_t *list, const guint16 type, const int nth);
+aim_tlv_t *aim_tlv_gettlv(GSList *list, guint16 type, const int nth);
+int aim_tlv_getlength(GSList *list, guint16 type, const int nth);
+char *aim_tlv_getstr(GSList *list, const guint16 type, const int nth);
+guint8 aim_tlv_get8(GSList *list, const guint16 type, const int nth);
+guint16 aim_tlv_get16(GSList *list, const guint16 type, const int nth);
+guint32 aim_tlv_get32(GSList *list, const guint16 type, const int nth);
 
 /* TLV list handling functions */
-aim_tlvlist_t *aim_tlvlist_read(ByteStream *bs);
-aim_tlvlist_t *aim_tlvlist_readnum(ByteStream *bs, guint16 num);
-aim_tlvlist_t *aim_tlvlist_readlen(ByteStream *bs, guint16 len);
-aim_tlvlist_t *aim_tlvlist_copy(aim_tlvlist_t *orig);
+GSList *aim_tlvlist_read(ByteStream *bs);
+GSList *aim_tlvlist_readnum(ByteStream *bs, guint16 num);
+GSList *aim_tlvlist_readlen(ByteStream *bs, guint16 len);
+GSList *aim_tlvlist_copy(GSList *orig);
 
-int aim_tlvlist_count(aim_tlvlist_t **list);
-int aim_tlvlist_size(aim_tlvlist_t **list);
-int aim_tlvlist_cmp(aim_tlvlist_t *one, aim_tlvlist_t *two);
-int aim_tlvlist_write(ByteStream *bs, aim_tlvlist_t **list);
-void aim_tlvlist_free(aim_tlvlist_t **list);
+int aim_tlvlist_count(GSList *list);
+int aim_tlvlist_size(GSList *list);
+int aim_tlvlist_cmp(GSList *one, GSList *two);
+int aim_tlvlist_write(ByteStream *bs, GSList **list);
+void aim_tlvlist_free(GSList *list);
 
-int aim_tlvlist_add_raw(aim_tlvlist_t **list, const guint16 type, const guint16 length, const guint8 *value);
-int aim_tlvlist_add_noval(aim_tlvlist_t **list, const guint16 type);
-int aim_tlvlist_add_8(aim_tlvlist_t **list, const guint16 type, const guint8 value);
-int aim_tlvlist_add_16(aim_tlvlist_t **list, const guint16 type, const guint16 value);
-int aim_tlvlist_add_32(aim_tlvlist_t **list, const guint16 type, const guint32 value);
-int aim_tlvlist_add_str(aim_tlvlist_t **list, const guint16 type, const char *value);
-int aim_tlvlist_add_caps(aim_tlvlist_t **list, const guint16 type, const guint32 caps);
-int aim_tlvlist_add_userinfo(aim_tlvlist_t **list, guint16 type, aim_userinfo_t *userinfo);
-int aim_tlvlist_add_chatroom(aim_tlvlist_t **list, guint16 type, guint16 exchange, const char *roomname, guint16 instance);
-int aim_tlvlist_add_frozentlvlist(aim_tlvlist_t **list, guint16 type, aim_tlvlist_t **tl);
+int aim_tlvlist_add_raw(GSList **list, const guint16 type, const guint16 length, const guint8 *value);
+int aim_tlvlist_add_noval(GSList **list, const guint16 type);
+int aim_tlvlist_add_8(GSList **list, const guint16 type, const guint8 value);
+int aim_tlvlist_add_16(GSList **list, const guint16 type, const guint16 value);
+int aim_tlvlist_add_32(GSList **list, const guint16 type, const guint32 value);
+int aim_tlvlist_add_str(GSList **list, const guint16 type, const char *value);
+int aim_tlvlist_add_caps(GSList **list, const guint16 type, const guint32 caps);
+int aim_tlvlist_add_userinfo(GSList **list, guint16 type, aim_userinfo_t *userinfo);
+int aim_tlvlist_add_chatroom(GSList **list, guint16 type, guint16 exchange, const char *roomname, guint16 instance);
+int aim_tlvlist_add_frozentlvlist(GSList **list, guint16 type, GSList **tl);
 
-int aim_tlvlist_replace_raw(aim_tlvlist_t **list, const guint16 type, const guint16 lenth, const guint8 *value);
-int aim_tlvlist_replace_str(aim_tlvlist_t **list, const guint16 type, const char *str);
-int aim_tlvlist_replace_noval(aim_tlvlist_t **list, const guint16 type);
-int aim_tlvlist_replace_8(aim_tlvlist_t **list, const guint16 type, const guint8 value);
-int aim_tlvlist_replace_16(aim_tlvlist_t **list, const guint16 type, const guint16 value);
-int aim_tlvlist_replace_32(aim_tlvlist_t **list, const guint16 type, const guint32 value);
+int aim_tlvlist_replace_raw(GSList **list, const guint16 type, const guint16 lenth, const guint8 *value);
+int aim_tlvlist_replace_str(GSList **list, const guint16 type, const char *str);
+int aim_tlvlist_replace_noval(GSList **list, const guint16 type);
+int aim_tlvlist_replace_8(GSList **list, const guint16 type, const guint8 value);
+int aim_tlvlist_replace_16(GSList **list, const guint16 type, const guint16 value);
+int aim_tlvlist_replace_32(GSList **list, const guint16 type, const guint32 value);
 
-void aim_tlvlist_remove(aim_tlvlist_t **list, const guint16 type);
+void aim_tlvlist_remove(GSList **list, const guint16 type);
 
 
 
--- a/libpurple/protocols/oscar/peer.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/peer.c	Mon Jun 18 01:48:35 2007 +0000
@@ -173,12 +173,12 @@
 		purple_input_remove(conn->watcher_outgoing);
 		conn->watcher_outgoing = 0;
 	}
-	if (conn->listenerfd != -1)
+	if (conn->listenerfd >= 0)
 	{
 		close(conn->listenerfd);
 		conn->listenerfd = -1;
 	}
-	if (conn->fd != -1)
+	if (conn->fd >= 0)
 	{
 		close(conn->fd);
 		conn->fd = -1;
@@ -310,7 +310,7 @@
 		}
 
 		/* If there was an error then close the connection */
-		if (read == -1)
+		if (read < 0)
 		{
 			if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
 				/* No worries */
@@ -360,7 +360,7 @@
 		return;
 	}
 
-	if (read == -1)
+	if (read < 0)
 	{
 		if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
 			/* No worries */
@@ -422,7 +422,7 @@
 	wrotelen = send(conn->fd, conn->buffer_outgoing->outptr, writelen, 0);
 	if (wrotelen <= 0)
 	{
-		if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
+		if (wrotelen < 0 && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
 			/* No worries */
 			return;
 
@@ -462,7 +462,7 @@
 	purple_circ_buffer_append(conn->buffer_outgoing, bs->data, bs->len);
 
 	/* If we haven't already started writing stuff, then start the cycle */
-	if ((conn->watcher_outgoing == 0) && (conn->fd != -1))
+	if ((conn->watcher_outgoing == 0) && (conn->fd >= 0))
 	{
 		conn->watcher_outgoing = purple_input_add(conn->fd,
 				PURPLE_INPUT_WRITE, send_cb, conn);
@@ -596,7 +596,7 @@
 	purple_debug_info("oscar", "Accepting connection on listener socket.\n");
 
 	conn->fd = accept(conn->listenerfd, &addr, &addrlen);
-	if (conn->fd == -1)
+	if (conn->fd < 0)
 	{
 		if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
 			/* No connection yet--no worries */
@@ -640,7 +640,7 @@
 	conn = data;
 	conn->listen_data = NULL;
 
-	if (listenerfd == -1)
+	if (listenerfd < 0)
 	{
 		/* Could not open listener socket */
 		peer_connection_trynext(conn);
--- a/libpurple/protocols/oscar/peer_proxy.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/peer_proxy.c	Mon Jun 18 01:48:35 2007 +0000
@@ -224,7 +224,7 @@
 		}
 
 		/* If there was an error then close the connection */
-		if (read == -1)
+		if (read < 0)
 		{
 			if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
 				/* No worries */
@@ -285,7 +285,8 @@
 			return;
 		}
 
-		if (read == -1)
+		/* If there was an error then close the connection */
+		if (read < 0)
 		{
 			if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
 				/* No worries */
--- a/libpurple/protocols/oscar/tlv.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/oscar/tlv.c	Mon Jun 18 01:48:35 2007 +0000
@@ -18,7 +18,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
-
 #include "oscar.h"
 
 static aim_tlv_t *
@@ -35,17 +34,57 @@
 }
 
 static void
-freetlv(aim_tlv_t **oldtlv)
+freetlv(aim_tlv_t *oldtlv)
 {
+	g_free(oldtlv->value);
+	g_free(oldtlv);
+}
 
-	if (!oldtlv || !*oldtlv)
-		return;
+static GSList *
+aim_tlv_read(GSList *list, ByteStream *bs)
+{
+	guint16 type, length;
+	aim_tlv_t *tlv;
+
+	type = byte_stream_get16(bs);
+	length = byte_stream_get16(bs);
 
-	g_free((*oldtlv)->value);
-	g_free(*oldtlv);
-	*oldtlv = NULL;
+#if 0
+	/*
+	 * This code hasn't been needed in years.  It's been commented
+	 * out since 2003, at the latest.  It seems likely that it was
+	 * just a bug in their server code that has since been fixed.
+	 * In any case, here's the orignal comment, kept for historical
+	 * purposes:
+	 *
+	 * Okay, so now AOL has decided that any TLV of
+	 * type 0x0013 can only be two bytes, despite
+	 * what the actual given length is.  So here
+	 * we dump any invalid TLVs of that sort.  Hopefully
+	 * there's no special cases to this special case.
+	 *   - mid (30jun2000)
+	 */
+	if ((type == 0x0013) && (length != 0x0002)) {
+		length = 0x0002;
+		return list;
+	}
+#endif
+	if (length > byte_stream_empty(bs)) {
+		aim_tlvlist_free(list);
+		return NULL;
+	}
 
-	return;
+	tlv = createtlv(type, length, NULL);
+	if (tlv->length > 0) {
+		tlv->value = byte_stream_getraw(bs, length);
+		if (!tlv->value) {
+			freetlv(tlv);
+			aim_tlvlist_free(list);
+			return NULL;
+		}
+	}
+
+	return g_slist_prepend(list, tlv);
 }
 
 /**
@@ -56,7 +95,7 @@
  * routines.  When done with a TLV chain, aim_tlvlist_free() should
  * be called to free the dynamic substructures.
  *
- * XXX There should be a flag setable here to have the tlvlist contain
+ * TODO: 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
@@ -65,56 +104,17 @@
  * @param bs Input bstream
  * @return Return the TLV chain read
  */
-aim_tlvlist_t *aim_tlvlist_read(ByteStream *bs)
+GSList *aim_tlvlist_read(ByteStream *bs)
 {
-	aim_tlvlist_t *list = NULL, *cur;
+	GSList *list = NULL;
 
 	while (byte_stream_empty(bs) > 0) {
-		guint16 type, length;
-
-		type = byte_stream_get16(bs);
-		length = byte_stream_get16(bs);
-
-#if 0 /* temporarily disabled until I know if they're still doing it or not */
-		/*
-		 * Okay, so now AOL has decided that any TLV of
-		 * type 0x0013 can only be two bytes, despite
-		 * what the actual given length is.  So here
-		 * we dump any invalid TLVs of that sort.  Hopefully
-		 * there's no special cases to this special case.
-		 *   - mid (30jun2000)
-		 */
-		if ((type == 0x0013) && (length != 0x0002))
-			length = 0x0002;
-#else
-		if (0)
-			;
-#endif
-		else {
-
-			if (length > byte_stream_empty(bs)) {
-				aim_tlvlist_free(&list);
-				return NULL;
-			}
-
-			cur = g_new0(aim_tlvlist_t, 1);
-			cur->tlv = createtlv(type, length, NULL);
-			if (cur->tlv->length > 0) {
-				cur->tlv->value = byte_stream_getraw(bs, length);
-				if (!cur->tlv->value) {
-					freetlv(&cur->tlv);
-					g_free(cur);
-					aim_tlvlist_free(&list);
-					return NULL;
-				}
-			}
-
-			cur->next = list;
-			list = cur;
-		}
+		list = aim_tlv_read(list, bs);
+		if (list == NULL)
+			return NULL;
 	}
 
-	return list;
+	return g_slist_reverse(list);
 }
 
 /**
@@ -125,7 +125,7 @@
  * routines.  When done with a TLV chain, aim_tlvlist_free() should
  * be called to free the dynamic substructures.
  *
- * XXX There should be a flag setable here to have the tlvlist contain
+ * TODO: 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
@@ -138,40 +138,18 @@
  *        preceded by the number of TLVs.  So you can limit that with this.
  * @return Return the TLV chain read
  */
-aim_tlvlist_t *aim_tlvlist_readnum(ByteStream *bs, guint16 num)
+GSList *aim_tlvlist_readnum(ByteStream *bs, guint16 num)
 {
-	aim_tlvlist_t *list = NULL, *cur;
+	GSList *list = NULL;
 
 	while ((byte_stream_empty(bs) > 0) && (num != 0)) {
-		guint16 type, length;
-
-		type = byte_stream_get16(bs);
-		length = byte_stream_get16(bs);
-
-		if (length > byte_stream_empty(bs)) {
-			aim_tlvlist_free(&list);
+		list = aim_tlv_read(list, bs);
+		if (list == NULL)
 			return NULL;
-		}
-
-		cur = g_new0(aim_tlvlist_t, 1);
-		cur->tlv = createtlv(type, length, NULL);
-		if (cur->tlv->length > 0) {
-			cur->tlv->value = byte_stream_getraw(bs, length);
-			if (!cur->tlv->value) {
-				freetlv(&cur->tlv);
-				g_free(cur);
-				aim_tlvlist_free(&list);
-				return NULL;
-			}
-		}
-
-		if (num > 0)
-			num--;
-		cur->next = list;
-		list = cur;
+		num--;
 	}
 
-	return list;
+	return g_slist_reverse(list);
 }
 
 /**
@@ -182,7 +160,7 @@
  * routines.  When done with a TLV chain, aim_tlvlist_free() should
  * be called to free the dynamic substructures.
  *
- * XXX There should be a flag setable here to have the tlvlist contain
+ * TODO: 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
@@ -195,39 +173,19 @@
  *        preceded by the length of the TLVs.  So you can limit that with this.
  * @return Return the TLV chain read
  */
-aim_tlvlist_t *aim_tlvlist_readlen(ByteStream *bs, guint16 len)
+GSList *aim_tlvlist_readlen(ByteStream *bs, guint16 len)
 {
-	aim_tlvlist_t *list = NULL, *cur;
+	GSList *list = NULL;
 
 	while ((byte_stream_empty(bs) > 0) && (len > 0)) {
-		guint16 type, length;
-
-		type = byte_stream_get16(bs);
-		length = byte_stream_get16(bs);
-
-		if (length > byte_stream_empty(bs)) {
-			aim_tlvlist_free(&list);
+		list = aim_tlv_read(list, bs);
+		if (list == NULL)
 			return NULL;
-		}
 
-		cur = g_new0(aim_tlvlist_t, 1);
-		cur->tlv = createtlv(type, length, NULL);
-		if (cur->tlv->length > 0) {
-			cur->tlv->value = byte_stream_getraw(bs, length);
-			if (!cur->tlv->value) {
-				freetlv(&cur->tlv);
-				g_free(cur);
-				aim_tlvlist_free(&list);
-				return NULL;
-			}
-		}
-
-		len -= aim_tlvlist_size(&cur);
-		cur->next = list;
-		list = cur;
+		len -= 2 + 2 + ((aim_tlv_t *)list->data)->length;
 	}
 
-	return list;
+	return g_slist_reverse(list);
 }
 
 /**
@@ -237,12 +195,14 @@
  * @param orig The TLV chain you want to make a copy of.
  * @return A newly allocated TLV chain.
  */
-aim_tlvlist_t *aim_tlvlist_copy(aim_tlvlist_t *orig)
+GSList *aim_tlvlist_copy(GSList *orig)
 {
-	aim_tlvlist_t *new = NULL;
+	GSList *new = NULL;
+	aim_tlv_t *tlv;
 
-	while (orig) {
-		aim_tlvlist_add_raw(&new, orig->tlv->type, orig->tlv->length, orig->tlv->value);
+	while (orig != NULL) {
+		tlv = orig->data;
+		aim_tlvlist_add_raw(&new, tlv->type, tlv->length, tlv->value);
 		orig = orig->next;
 	}
 
@@ -257,15 +217,15 @@
  * @param two The other TLV chain to compare.
  * @return Return 0 if the lists are the same, return 1 if they are different.
  */
-int aim_tlvlist_cmp(aim_tlvlist_t *one, aim_tlvlist_t *two)
+int aim_tlvlist_cmp(GSList *one, GSList *two)
 {
 	ByteStream bs1, bs2;
 
-	if (aim_tlvlist_size(&one) != aim_tlvlist_size(&two))
+	if (aim_tlvlist_size(one) != aim_tlvlist_size(two))
 		return 1;
 
-	byte_stream_new(&bs1, aim_tlvlist_size(&one));
-	byte_stream_new(&bs2, aim_tlvlist_size(&two));
+	byte_stream_new(&bs1, aim_tlvlist_size(one));
+	byte_stream_new(&bs2, aim_tlvlist_size(two));
 
 	aim_tlvlist_write(&bs1, &one);
 	aim_tlvlist_write(&bs2, &two);
@@ -291,26 +251,13 @@
  *
  * @param list Chain to be freed
  */
-void aim_tlvlist_free(aim_tlvlist_t **list)
+void aim_tlvlist_free(GSList *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;
+	while (list != NULL)
+	{
+		freetlv(list->data);
+		list = g_slist_delete_link(list, list);
 	}
-
-	list = NULL;
-
-	return;
 }
 
 /**
@@ -319,15 +266,15 @@
  * @param list Chain to be counted.
  * @return The number of TLVs stored in the passed chain.
  */
-int aim_tlvlist_count(aim_tlvlist_t **list)
+int aim_tlvlist_count(GSList *list)
 {
-	aim_tlvlist_t *cur;
+	GSList *cur;
 	int count;
 
-	if (!list || !*list)
+	if (list == NULL)
 		return 0;
 
-	for (cur = *list, count = 0; cur; cur = cur->next)
+	for (cur = list, count = 0; cur; cur = cur->next)
 		count++;
 
 	return count;
@@ -340,16 +287,16 @@
  * @return The number of bytes that would be needed to
  *         write the passed TLV chain to a data buffer.
  */
-int aim_tlvlist_size(aim_tlvlist_t **list)
+int aim_tlvlist_size(GSList *list)
 {
-	aim_tlvlist_t *cur;
+	GSList *cur;
 	int size;
 
-	if (!list || !*list)
+	if (list == NULL)
 		return 0;
 
-	for (cur = *list, size = 0; cur; cur = cur->next)
-		size += (4 + cur->tlv->length);
+	for (cur = list, size = 0; cur; cur = cur->next)
+		size += (4 + ((aim_tlv_t *)cur->data)->length);
 
 	return size;
 }
@@ -364,27 +311,20 @@
  * @param value String to add.
  * @return The size of the value added.
  */
-int aim_tlvlist_add_raw(aim_tlvlist_t **list, const guint16 type, const guint16 length, const guint8 *value)
+int aim_tlvlist_add_raw(GSList **list, const guint16 type, const guint16 length, const guint8 *value)
 {
-	aim_tlvlist_t *newtlv, *cur;
+	aim_tlv_t *tlv;
 
 	if (list == NULL)
 		return 0;
 
-	newtlv = g_new0(aim_tlvlist_t, 1);
-	newtlv->tlv = createtlv(type, length, NULL);
-	if (newtlv->tlv->length > 0)
-		newtlv->tlv->value = g_memdup(value, length);
+	tlv = createtlv(type, length, NULL);
+	if (tlv->length > 0)
+		tlv->value = g_memdup(value, length);
 
-	if (!*list)
-		*list = newtlv;
-	else {
-		for(cur = *list; cur->next; cur = cur->next)
-			;
-		cur->next = newtlv;
-	}
+	*list = g_slist_append(*list, tlv);
 
-	return newtlv->tlv->length;
+	return tlv->length;
 }
 
 /**
@@ -395,7 +335,7 @@
  * @param value Value to add.
  * @return The size of the value added.
  */
-int aim_tlvlist_add_8(aim_tlvlist_t **list, const guint16 type, const guint8 value)
+int aim_tlvlist_add_8(GSList **list, const guint16 type, const guint8 value)
 {
 	guint8 v8[1];
 
@@ -412,7 +352,7 @@
  * @param value Value to add.
  * @return The size of the value added.
  */
-int aim_tlvlist_add_16(aim_tlvlist_t **list, const guint16 type, const guint16 value)
+int aim_tlvlist_add_16(GSList **list, const guint16 type, const guint16 value)
 {
 	guint8 v16[2];
 
@@ -429,7 +369,7 @@
  * @param value Value to add.
  * @return The size of the value added.
  */
-int aim_tlvlist_add_32(aim_tlvlist_t **list, const guint16 type, const guint32 value)
+int aim_tlvlist_add_32(GSList **list, const guint16 type, const guint32 value)
 {
 	guint8 v32[4];
 
@@ -446,7 +386,7 @@
  * @param value Value to add.
  * @return The size of the value added.
  */
-int aim_tlvlist_add_str(aim_tlvlist_t **list, const guint16 type, const char *value)
+int aim_tlvlist_add_str(GSList **list, const guint16 type, const char *value)
 {
 	return aim_tlvlist_add_raw(list, type, strlen(value), (guint8 *)value);
 }
@@ -467,12 +407,12 @@
  * @param caps Bitfield of capability flags to send
  * @return The size of the value added.
  */
-int aim_tlvlist_add_caps(aim_tlvlist_t **list, const guint16 type, const guint32 caps)
+int aim_tlvlist_add_caps(GSList **list, const guint16 type, const guint32 caps)
 {
-	guint8 buf[16*16]; /* XXX icky fixed length buffer */
+	guint8 buf[256]; /* TODO: Don't use a fixed length buffer */
 	ByteStream bs;
 
-	if (!caps)
+	if (caps == 0)
 		return 0; /* nothing there anyway */
 
 	byte_stream_init(&bs, buf, sizeof(buf));
@@ -489,9 +429,9 @@
  * @param type TLV type to add.
  * @return The size of the value added.
  */
-int aim_tlvlist_add_userinfo(aim_tlvlist_t **list, guint16 type, aim_userinfo_t *userinfo)
+int aim_tlvlist_add_userinfo(GSList **list, guint16 type, aim_userinfo_t *userinfo)
 {
-	guint8 buf[1024]; /* bleh */
+	guint8 buf[1024]; /* TODO: Don't use a fixed length buffer */
 	ByteStream bs;
 
 	byte_stream_init(&bs, buf, sizeof(buf));
@@ -510,7 +450,7 @@
  * @param instance The instance.
  * @return The size of the value added.
  */
-int aim_tlvlist_add_chatroom(aim_tlvlist_t **list, guint16 type, guint16 exchange, const char *roomname, guint16 instance)
+int aim_tlvlist_add_chatroom(GSList **list, guint16 type, guint16 exchange, const char *roomname, guint16 instance)
 {
 	int len;
 	ByteStream bs;
@@ -536,7 +476,7 @@
  * @param type TLV type to add.
  * @return The size of the value added.
  */
-int aim_tlvlist_add_noval(aim_tlvlist_t **list, const guint16 type)
+int aim_tlvlist_add_noval(GSList **list, const guint16 type)
 {
 	return aim_tlvlist_add_raw(list, type, 0, NULL);
 }
@@ -546,7 +486,7 @@
  * 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.
+ * TODO: Should probably support sublists for real.
  *
  * This is so neat.
  *
@@ -557,19 +497,19 @@
  *         0 is returned if there was an error or if the destination
  *         TLV chain has length 0.
  */
-int aim_tlvlist_add_frozentlvlist(aim_tlvlist_t **list, guint16 type, aim_tlvlist_t **tl)
+int aim_tlvlist_add_frozentlvlist(GSList **list, guint16 type, GSList **tlvlist)
 {
 	int buflen;
 	ByteStream bs;
 
-	buflen = aim_tlvlist_size(tl);
+	buflen = aim_tlvlist_size(*tlvlist);
 
 	if (buflen <= 0)
 		return 0;
 
 	byte_stream_new(&bs, buflen);
 
-	aim_tlvlist_write(&bs, tl);
+	aim_tlvlist_write(&bs, tlvlist);
 
 	aim_tlvlist_add_raw(list, type, byte_stream_curpos(&bs), bs.data);
 
@@ -589,25 +529,33 @@
  * @param value String to add.
  * @return The length of the TLV.
  */
-int aim_tlvlist_replace_raw(aim_tlvlist_t **list, const guint16 type, const guint16 length, const guint8 *value)
+int aim_tlvlist_replace_raw(GSList **list, const guint16 type, const guint16 length, const guint8 *value)
 {
-	aim_tlvlist_t *cur;
+	GSList *cur;
+	aim_tlv_t *tlv;
 
 	if (list == NULL)
 		return 0;
 
-	for (cur = *list; ((cur != NULL) && (cur->tlv->type != type)); cur = cur->next);
+	for (cur = *list; cur != NULL; cur = cur->next)
+	{
+		tlv = cur->data;
+		if (tlv->type == type)
+			break;
+	}
+
 	if (cur == NULL)
+		/* TLV does not exist, so add a new one */
 		return aim_tlvlist_add_raw(list, type, length, value);
 
-	g_free(cur->tlv->value);
-	cur->tlv->length = length;
-	if (cur->tlv->length > 0) {
-		cur->tlv->value = g_memdup(value, length);
+	g_free(tlv->value);
+	tlv->length = length;
+	if (tlv->length > 0) {
+		tlv->value = g_memdup(value, length);
 	} else
-		cur->tlv->value = NULL;
+		tlv->value = NULL;
 
-	return cur->tlv->length;
+	return tlv->length;
 }
 
 /**
@@ -620,7 +568,7 @@
  * @param str String to add.
  * @return The length of the TLV.
  */
-int aim_tlvlist_replace_str(aim_tlvlist_t **list, const guint16 type, const char *str)
+int aim_tlvlist_replace_str(GSList **list, const guint16 type, const char *str)
 {
 	return aim_tlvlist_replace_raw(list, type, strlen(str), (const guchar *)str);
 }
@@ -634,7 +582,7 @@
  * @param type TLV type.
  * @return The length of the TLV.
  */
-int aim_tlvlist_replace_noval(aim_tlvlist_t **list, const guint16 type)
+int aim_tlvlist_replace_noval(GSList **list, const guint16 type)
 {
 	return aim_tlvlist_replace_raw(list, type, 0, NULL);
 }
@@ -649,7 +597,7 @@
  * @param value 8 bit value to add.
  * @return The length of the TLV.
  */
-int aim_tlvlist_replace_8(aim_tlvlist_t **list, const guint16 type, const guint8 value)
+int aim_tlvlist_replace_8(GSList **list, const guint16 type, const guint8 value)
 {
 	guint8 v8[1];
 
@@ -668,7 +616,7 @@
  * @param value 32 bit value to add.
  * @return The length of the TLV.
  */
-int aim_tlvlist_replace_32(aim_tlvlist_t **list, const guint16 type, const guint32 value)
+int aim_tlvlist_replace_32(GSList **list, const guint16 type, const guint32 value)
 {
 	guint8 v32[4];
 
@@ -678,36 +626,36 @@
 }
 
 /**
- * Remove a TLV of a given type.  If you attempt to remove a TLV that
- * does not exist, nothing happens.
+ * Remove all TLVs of a given type.  If you attempt to remove a TLV
+ * that does not exist, nothing happens.
  *
  * @param list Desination chain (%NULL pointer if empty).
  * @param type TLV type.
  */
-void aim_tlvlist_remove(aim_tlvlist_t **list, const guint16 type)
+void aim_tlvlist_remove(GSList **list, const guint16 type)
 {
-	aim_tlvlist_t *del;
+	GSList *cur, *next;
+	aim_tlv_t *tlv;
 
-	if (!list || !(*list))
+	if (list == NULL || *list == NULL)
 		return;
 
-	/* Remove the item from the list */
-	if ((*list)->tlv->type == type) {
-		del = *list;
-		*list = (*list)->next;
-	} else {
-		aim_tlvlist_t *cur;
-		for (cur=*list; (cur->next && (cur->next->tlv->type!=type)); cur=cur->next);
-		if (!cur->next)
-			return;
-		del = cur->next;
-		cur->next = del->next;
+	cur = *list;
+	while (cur != NULL)
+	{
+		tlv = cur->data;
+		next = cur->next;
+
+		if (tlv->type == type)
+		{
+			/* Delete this TLV */
+			*list = g_slist_delete_link(*list, cur);
+			g_free(tlv->value);
+			g_free(tlv);
+		}
+
+		cur = next;
 	}
-
-	/* Free the removed item */
-	g_free(del->tlv->value);
-	g_free(del->tlv);
-	g_free(del);
 }
 
 /**
@@ -718,32 +666,34 @@
  * aim_tlvlist_free() must still be called to free up the memory used
  * by the chain structures.
  *
- * XXX clean this up, make better use of bstreams
+ * TODO: Clean this up, make better use of bstreams
  *
  * @param bs Input bstream
  * @param list Source TLV chain
  * @return Return 0 if the destination bstream is too small.
  */
-int aim_tlvlist_write(ByteStream *bs, aim_tlvlist_t **list)
+int aim_tlvlist_write(ByteStream *bs, GSList **list)
 {
 	int goodbuflen;
-	aim_tlvlist_t *cur;
+	GSList *cur;
+	aim_tlv_t *tlv;
 
 	/* do an initial run to test total length */
-	goodbuflen = aim_tlvlist_size(list);
+	goodbuflen = aim_tlvlist_size(*list);
 
 	if (goodbuflen > byte_stream_empty(bs))
 		return 0; /* not enough buffer */
 
 	/* do the real write-out */
 	for (cur = *list; cur; cur = cur->next) {
-		byte_stream_put16(bs, cur->tlv->type);
-		byte_stream_put16(bs, cur->tlv->length);
-		if (cur->tlv->length)
-			byte_stream_putraw(bs, cur->tlv->value, cur->tlv->length);
+		tlv = cur->data;
+		byte_stream_put16(bs, tlv->type);
+		byte_stream_put16(bs, tlv->length);
+		if (tlv->length > 0)
+			byte_stream_putraw(bs, tlv->value, tlv->length);
 	}
 
-	return 1; /* XXX this is a nonsensical return */
+	return 1; /* TODO: This is a nonsensical return */
 }
 
 
@@ -760,17 +710,19 @@
  * @param nth Index of TLV of type to get.
  * @return The TLV you were looking for, or NULL if one could not be found.
  */
-aim_tlv_t *aim_tlv_gettlv(aim_tlvlist_t *list, const guint16 type, const int nth)
+aim_tlv_t *aim_tlv_gettlv(GSList *list, const guint16 type, const int nth)
 {
-	aim_tlvlist_t *cur;
+	GSList *cur;
+	aim_tlv_t *tlv;
 	int i;
 
-	for (cur = list, i = 0; cur; cur = cur->next) {
-		if (cur && cur->tlv) {
-			if (cur->tlv->type == type)
+	for (cur = list, i = 0; cur != NULL; cur = cur->next) {
+		tlv = cur->data;
+		if (tlv != NULL) { /* TODO: This NULL check shouldn't be needed */
+			if (tlv->type == type)
 				i++;
 			if (i >= nth)
-				return cur->tlv;
+				return tlv;
 		}
 	}
 
@@ -786,21 +738,15 @@
  * @return The length of the data in this TLV, or -1 if the TLV could not be
  *         found.  Unless -1 is returned, this value will be 2 bytes.
  */
-int aim_tlv_getlength(aim_tlvlist_t *list, const guint16 type, const int nth)
+int aim_tlv_getlength(GSList *list, const guint16 type, const int nth)
 {
-	aim_tlvlist_t *cur;
-	int i;
+	aim_tlv_t *tlv;
 
-	for (cur = list, i = 0; cur; cur = cur->next) {
-		if (cur && cur->tlv) {
-			if (cur->tlv->type == type)
-				i++;
-			if (i >= nth)
-				return cur->tlv->length;
-		}
-	}
+	tlv = aim_tlv_gettlv(list, type, nth);
+	if (tlv == NULL)
+		return -1;
 
-	return -1;
+	return tlv->length;
 }
 
 char *
@@ -825,11 +771,12 @@
  *         not be found.  This is a dynamic buffer and must be freed by the
  *         caller.
  */
-char *aim_tlv_getstr(aim_tlvlist_t *list, const guint16 type, const int nth)
+char *aim_tlv_getstr(GSList *list, const guint16 type, const int nth)
 {
 	aim_tlv_t *tlv;
 
-	if (!(tlv = aim_tlv_gettlv(list, type, nth)))
+	tlv = aim_tlv_gettlv(list, type, nth);
+	if (tlv == NULL)
 		return NULL;
 
 	return aim_tlv_getvalue_as_string(tlv);
@@ -845,12 +792,14 @@
  * @return The value the TLV you were looking for, or 0 if one could
  *         not be found.
  */
-guint8 aim_tlv_get8(aim_tlvlist_t *list, const guint16 type, const int nth)
+guint8 aim_tlv_get8(GSList *list, const guint16 type, const int nth)
 {
 	aim_tlv_t *tlv;
 
-	if (!(tlv = aim_tlv_gettlv(list, type, nth)))
+	tlv = aim_tlv_gettlv(list, type, nth);
+	if (tlv == NULL)
 		return 0; /* erm */
+
 	return aimutil_get8(tlv->value);
 }
 
@@ -864,12 +813,14 @@
  * @return The value the TLV you were looking for, or 0 if one could
  *         not be found.
  */
-guint16 aim_tlv_get16(aim_tlvlist_t *list, const guint16 type, const int nth)
+guint16 aim_tlv_get16(GSList *list, const guint16 type, const int nth)
 {
 	aim_tlv_t *tlv;
 
-	if (!(tlv = aim_tlv_gettlv(list, type, nth)))
+	tlv = aim_tlv_gettlv(list, type, nth);
+	if (tlv == NULL)
 		return 0; /* erm */
+
 	return aimutil_get16(tlv->value);
 }
 
@@ -883,11 +834,13 @@
  * @return The value the TLV you were looking for, or 0 if one could
  *         not be found.
  */
-guint32 aim_tlv_get32(aim_tlvlist_t *list, const guint16 type, const int nth)
+guint32 aim_tlv_get32(GSList *list, const guint16 type, const int nth)
 {
 	aim_tlv_t *tlv;
 
-	if (!(tlv = aim_tlv_gettlv(list, type, nth)))
+	tlv = aim_tlv_gettlv(list, type, nth);
+	if (tlv == NULL)
 		return 0; /* erm */
+
 	return aimutil_get32(tlv->value);
 }
--- a/libpurple/protocols/qq/AUTHORS	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/qq/AUTHORS	Mon Jun 18 01:48:35 2007 +0000
@@ -1,7 +1,7 @@
 Code Contributors
 =====
 puzzlebird  : original author
-gfhuang     : patches for gaim 2.0.0beta2, maintainer
+gfhuang     : patches for libpurple 2.0.0beta2, maintainer
 henryouly   : file transfer, udp sock5 proxy and qq_show, maintainer
 hzhr        : maintainer
 joymarquis  : maintainer
@@ -10,7 +10,7 @@
 yyw         : improved performance on PPC linux
 lvxiang     : provided ip to location original code
 csyfek      : faces
-markhuetsch : OpenQ merge into gaim, maintainer 2006-2007
+markhuetsch : OpenQ merge into libpurple, maintainer 2006-2007
 
 Acknowledgement
 =====
--- a/libpurple/protocols/qq/header_info.h	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/qq/header_info.h	Mon Jun 18 01:48:35 2007 +0000
@@ -33,7 +33,7 @@
 #define QQ_PACKET_TAG           0x02	/* all QQ text packets starts with it */
 #define QQ_PACKET_TAIL          0x03	/* all QQ text packets end with it */
 
-#define QQ_CLIENT       0x0f15
+#define QQ_CLIENT       0x0E1B
 
 /* list of known QQ commands */
 enum {
--- a/libpurple/protocols/silc/README	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/silc/README	Mon Jun 18 01:48:35 2007 +0000
@@ -2,19 +2,19 @@
 ==================
 
 This is the Purple protocol plugin of the protocol called Secure Internet
-Live Conferencing (SILC).  The implementation will use the SILC Toolkit, 
-freely available from the http://silcnet.org/ site, for the actual SILC 
+Live Conferencing (SILC).  The implementation will use the SILC Toolkit,
+freely available from the http://silcnet.org/ site, for the actual SILC
 protocol implementation.
 
-To include SILC into Purple, one needs to first compile and install 
+To include SILC into Purple, one needs to first compile and install
 the SILC Toolkit.  It is done as follows:
 
-	./configure --enable-shared
+	./configure
 	make
 	make install
 
-This will compile shared libraries of the SILC Toolkit.  If the --prefix 
-is not given to ./configure, the binaries are installed into the 
+This will compile shared libraries of the SILC Toolkit.  If the --prefix
+is not given to ./configure, the binaries are installed into the
 /usr/local/silc directory.
 
 Once the Toolkit is installed one needs to tell Purple's ./configure
--- a/libpurple/protocols/silc/TODO	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/silc/TODO	Mon Jun 18 01:48:35 2007 +0000
@@ -1,14 +1,6 @@
 Features TODO (maybe)
 =====================
 
-Sending images
-	- Sending images to channel too, if libpurple allows it.
-
 Preferences
 	- Add joined channels to buddy list automatically (during
 	  session)
-	- Add joined channels to buddy list automatically permanently
-
-Buddy icon
-	- After SILC Toolkit 1.0.2 buddy icon support can be added
-	  (SILC_ATTERIBUTE_USER_ICON).
--- a/libpurple/protocols/silc/buddy.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/silc/buddy.c	Mon Jun 18 01:48:35 2007 +0000
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2004 Pekka Riikonen
+  Copyright (C) 2004 - 2007 Pekka Riikonen
 
   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
@@ -17,7 +17,7 @@
 
 */
 
-#include "silcincludes.h"
+#include "silc.h"
 #include "silcclient.h"
 #include "silcpurple.h"
 #include "wb.h"
@@ -29,7 +29,7 @@
 
 static void
 silcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name,
-			 			 gboolean force_local);
+			   gboolean force_local);
 
 typedef struct {
 	char *nick;
@@ -38,10 +38,10 @@
 
 static void
 silcpurple_buddy_keyagr_resolved(SilcClient client,
-			       SilcClientConnection conn,
-			       SilcClientEntry *clients,
-			       SilcUInt32 clients_count,
-			       void *context)
+				 SilcClientConnection conn,
+				 SilcStatus status,
+				 SilcDList clients,
+				 void *context)
 {
 	PurpleConnection *gc = client->application;
 	SilcPurpleResolve r = context;
@@ -62,21 +62,16 @@
 	silc_free(r);
 }
 
-typedef struct {
-	gboolean responder;
-} *SilcPurpleKeyAgr;
-
 static void
 silcpurple_buddy_keyagr_cb(SilcClient client,
-			 SilcClientConnection conn,
-			 SilcClientEntry client_entry,
-			 SilcKeyAgreementStatus status,
-			 SilcSKEKeyMaterial *key,
-			 void *context)
+			   SilcClientConnection conn,
+			   SilcClientEntry client_entry,
+			   SilcKeyAgreementStatus status,
+			   SilcSKEKeyMaterial key,
+			   void *context)
 {
 	PurpleConnection *gc = client->application;
 	SilcPurple sg = gc->proto_data;
-	SilcPurpleKeyAgr a = context;
 
 	if (!sg->conn)
 		return;
@@ -90,13 +85,13 @@
 			/* Set the private key for this client */
 			silc_client_del_private_message_key(client, conn, client_entry);
 			silc_client_add_private_message_key_ske(client, conn, client_entry,
-								NULL, NULL, key, a->responder);
+								NULL, NULL, key);
 			silc_ske_free_key_material(key);
 
-			
+
 			/* Open IM window */
 			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
-									client_entry->nickname, sg->account);
+								      client_entry->nickname, sg->account);
 			if (convo) {
 				/* we don't have windows in the core anymore...but we may want to
 				 * provide some method for asking the UI to show the window
@@ -104,7 +99,7 @@
 				 */
 			} else {
 				convo = purple_conversation_new(PURPLE_CONV_TYPE_IM, sg->account,
-							      client_entry->nickname);
+								client_entry->nickname);
 			}
 			g_snprintf(tmp, sizeof(tmp), "%s [private key]", client_entry->nickname);
 			purple_conversation_set_title(convo, tmp);
@@ -113,7 +108,7 @@
 
 	case SILC_KEY_AGREEMENT_ERROR:
 		purple_notify_error(gc, _("Key Agreement"),
-				  _("Error occurred during key agreement"), NULL);
+				    _("Error occurred during key agreement"), NULL);
 		break;
 
 	case SILC_KEY_AGREEMENT_FAILURE:
@@ -122,53 +117,48 @@
 
 	case SILC_KEY_AGREEMENT_TIMEOUT:
 		purple_notify_error(gc, _("Key Agreement"),
-				  _("Timeout during key agreement"), NULL);
+				    _("Timeout during key agreement"), NULL);
 		break;
 
 	case SILC_KEY_AGREEMENT_ABORTED:
 		purple_notify_error(gc, _("Key Agreement"),
-				  _("Key agreement was aborted"), NULL);
+				    _("Key agreement was aborted"), NULL);
 		break;
 
 	case SILC_KEY_AGREEMENT_ALREADY_STARTED:
 		purple_notify_error(gc, _("Key Agreement"),
-				  _("Key agreement is already started"), NULL);
+				    _("Key agreement is already started"), NULL);
 		break;
 
 	case SILC_KEY_AGREEMENT_SELF_DENIED:
 		purple_notify_error(gc, _("Key Agreement"),
-				  _("Key agreement cannot be started with yourself"),
-				  NULL);
+				    _("Key agreement cannot be started with yourself"),
+				    NULL);
 		break;
 
 	default:
 		break;
 	}
-
-	silc_free(a);
 }
 
 static void
 silcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name,
-			 gboolean force_local)
+			   gboolean force_local)
 {
 	SilcPurple sg = gc->proto_data;
-	SilcClientEntry *clients;
-	SilcUInt32 clients_count;
+	SilcDList clients;
+	SilcClientEntry client_entry;
+	SilcClientConnectionParams params;
 	char *local_ip = NULL, *remote_ip = NULL;
 	gboolean local = TRUE;
-	char *nickname;
-	SilcPurpleKeyAgr a;
+	SilcSocket sock;
 
 	if (!sg->conn || !name)
 		return;
 
-	if (!silc_parse_userfqdn(name, &nickname, NULL))
-		return;
-
 	/* Find client entry */
-	clients = silc_client_get_clients_local(sg->client, sg->conn, nickname, name,
-						&clients_count);
+	clients = silc_client_get_clients_local(sg->client, sg->conn, name,
+						FALSE);
 	if (!clients) {
 		/* Resolve unknown user */
 		SilcPurpleResolve r = silc_calloc(1, sizeof(*r));
@@ -176,12 +166,14 @@
 			return;
 		r->nick = g_strdup(name);
 		r->gc = gc;
-		silc_client_get_clients(sg->client, sg->conn, nickname, NULL,
+		silc_client_get_clients(sg->client, sg->conn, name, NULL,
 					silcpurple_buddy_keyagr_resolved, r);
-		silc_free(nickname);
 		return;
 	}
 
+	silc_socket_stream_get_info(silc_packet_stream_get_stream(sg->conn->stream),
+				    &sock, NULL, NULL, NULL);
+
 	/* Resolve the local IP from the outgoing socket connection.  We resolve
 	   it to check whether we have a private range IP address or public IP
 	   address.  If we have public then we will assume that we are not behind
@@ -196,14 +188,14 @@
 
 	   Naturally this algorithm does not always get things right. */
 
-	if (silc_net_check_local_by_sock(sg->conn->sock->sock, NULL, &local_ip)) {
+	if (silc_net_check_local_by_sock(sock, NULL, &local_ip)) {
 		/* Check if the IP is private */
 		if (!force_local && silcpurple_ip_is_private(local_ip)) {
 			local = FALSE;
 
 			/* Local IP is private, resolve the remote server IP to see whether
 			   we are talking to Internet or just on LAN. */
-			if (silc_net_check_host_by_sock(sg->conn->sock->sock, NULL,
+			if (silc_net_check_host_by_sock(sock, NULL,
 							&remote_ip))
 				if (silcpurple_ip_is_private(remote_ip))
 					/* We assume we are in LAN.  Let's provide
@@ -218,19 +210,24 @@
 	if (local && !local_ip)
 		local_ip = silc_net_localip();
 
-	a = silc_calloc(1, sizeof(*a));
-	if (!a)
-		return;
-	a->responder = local;
+	silc_dlist_start(clients);
+	client_entry = silc_dlist_get(clients);
+
+	memset(&params, 0, sizeof(params));
+	params.timeout_secs = 60;
+	if (local)
+	  /* Provide connection point */
+	  params.local_ip = local_ip;
 
 	/* Send the key agreement request */
-	silc_client_send_key_agreement(sg->client, sg->conn, clients[0],
-				       local ? local_ip : NULL, NULL, 0, 60,
-				       silcpurple_buddy_keyagr_cb, a);
+	silc_client_send_key_agreement(sg->client, sg->conn, client_entry,
+				       &params, sg->public_key,
+				       sg->private_key,
+				       silcpurple_buddy_keyagr_cb, NULL);
 
 	silc_free(local_ip);
 	silc_free(remote_ip);
-	silc_free(clients);
+	silc_client_list_free(sg->client, sg->conn, clients);
 }
 
 typedef struct {
@@ -244,8 +241,8 @@
 static void
 silcpurple_buddy_keyagr_request_cb(SilcPurpleKeyAgrAsk a, gint id)
 {
-	SilcPurpleKeyAgr ai;
 	SilcClientEntry client_entry;
+	SilcClientConnectionParams params;
 
 	if (id != 1)
 		goto out;
@@ -255,26 +252,27 @@
 						    &a->client_id);
 	if (!client_entry) {
 		purple_notify_error(a->client->application, _("Key Agreement"),
-				  _("The remote user is not present in the network any more"),
-				  NULL);
+				    _("The remote user is not present in the network any more"),
+				    NULL);
 		goto out;
 	}
 
 	/* If the hostname was provided by the requestor perform the key agreement
 	   now.  Otherwise, we will send him a request to connect to us. */
 	if (a->hostname) {
-		ai = silc_calloc(1, sizeof(*ai));
-		if (!ai)
-			goto out;
-		ai->responder = FALSE;
-		silc_client_perform_key_agreement(a->client, a->conn, client_entry,
+		memset(&params, 0, sizeof(params));
+		params.timeout_secs = 60;
+		silc_client_perform_key_agreement(a->client, a->conn,
+						  client_entry, &params,
+						  a->conn->public_key,
+						  a->conn->private_key,
 						  a->hostname, a->port,
-						  silcpurple_buddy_keyagr_cb, ai);
+						  silcpurple_buddy_keyagr_cb, NULL);
 	} else {
 		/* Send request.  Force us as the point of connection since requestor
 		   did not provide the point of connection. */
 		silcpurple_buddy_keyagr_do(a->client->application,
-					 client_entry->nickname, TRUE);
+					   client_entry->nickname, TRUE);
 	}
 
  out:
@@ -283,14 +281,19 @@
 }
 
 void silcpurple_buddy_keyagr_request(SilcClient client,
-				   SilcClientConnection conn,
-				   SilcClientEntry client_entry,
-				   const char *hostname, SilcUInt16 port)
+				     SilcClientConnection conn,
+				     SilcClientEntry client_entry,
+				     const char *hostname, SilcUInt16 port,
+				     SilcUInt16 protocol)
 {
 	char tmp[128], tmp2[128];
 	SilcPurpleKeyAgrAsk a;
 	PurpleConnection *gc = client->application;
 
+	/* For now Pidgin don't support UDP key agreement */
+	if (protocol == 1)
+	  return;
+
 	g_snprintf(tmp, sizeof(tmp),
 		   _("Key agreement request received from %s. Would you like to "
 		     "perform the key agreement?"), client_entry->nickname);
@@ -304,15 +307,15 @@
 		return;
 	a->client = client;
 	a->conn = conn;
-	a->client_id = *client_entry->id;
+	a->client_id = client_entry->id;
 	if (hostname)
 		a->hostname = strdup(hostname);
 	a->port = port;
 
 	purple_request_action(client->application, _("Key Agreement Request"), tmp,
-			    hostname ? tmp2 : NULL, 1, gc->account, client_entry->nickname,
-				NULL, a, 2, _("Yes"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb),
-			    _("No"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb));
+			      hostname ? tmp2 : NULL, 1, gc->account, client_entry->nickname,
+			      NULL, a, 2, _("Yes"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb),
+			      _("No"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb));
 }
 
 static void
@@ -333,9 +336,7 @@
 	PurpleBuddy *b;
 	PurpleConnection *gc;
         SilcPurple sg;
-	char *nickname;
-	SilcClientEntry *clients;
-	SilcUInt32 clients_count;
+	SilcDList clients;
 
 	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
 
@@ -343,23 +344,16 @@
 	gc = purple_account_get_connection(b->account);
 	sg = gc->proto_data;
 
-	if (!silc_parse_userfqdn(b->name, &nickname, NULL))
-		return;
-
 	/* Find client entry */
 	clients = silc_client_get_clients_local(sg->client, sg->conn,
-						nickname, b->name,
-						&clients_count);
-	if (!clients) {
-		silc_free(nickname);
+						b->name, FALSE);
+	if (!clients)
 		return;
-	}
 
-	clients[0]->prv_resp = FALSE;
+	silc_dlist_start(clients);
 	silc_client_del_private_message_key(sg->client, sg->conn,
-					    clients[0]);
-	silc_free(clients);
-	silc_free(nickname);
+					    silc_dlist_get(clients));
+	silc_client_list_free(sg->client, sg->conn, clients);
 }
 
 typedef struct {
@@ -386,8 +380,8 @@
 						    &p->client_id);
 	if (!client_entry) {
 		purple_notify_error(p->client->application, _("IM With Password"),
-				  _("The remote user is not present in the network any more"),
-				  NULL);
+				    _("The remote user is not present in the network any more"),
+				    NULL);
 		silc_free(p);
 		return;
 	}
@@ -398,21 +392,16 @@
 	silc_client_add_private_message_key(p->client, p->conn,
 					    client_entry, NULL, NULL,
 					    (unsigned char *)passphrase,
-					    strlen(passphrase), FALSE,
-					    client_entry->prv_resp);
-	if (!client_entry->prv_resp)
-		silc_client_send_private_message_key_request(p->client,
-							     p->conn,
-							     client_entry);
+					    strlen(passphrase));
         silc_free(p);
 }
 
 static void
 silcpurple_buddy_privkey_resolved(SilcClient client,
-				SilcClientConnection conn,
-				SilcClientEntry *clients,
-				SilcUInt32 clients_count,
-				void *context)
+				  SilcClientConnection conn,
+				  SilcStatus status,
+				  SilcDList clients,
+				  void *context)
 {
 	char tmp[256];
 
@@ -434,42 +423,39 @@
 silcpurple_buddy_privkey(PurpleConnection *gc, const char *name)
 {
 	SilcPurple sg = gc->proto_data;
-	char *nickname;
 	SilcPurplePrivkey p;
-	SilcClientEntry *clients;
-	SilcUInt32 clients_count;
+	SilcDList clients;
+	SilcClientEntry client_entry;
 
 	if (!name)
 		return;
-	if (!silc_parse_userfqdn(name, &nickname, NULL))
-		return;
 
 	/* Find client entry */
 	clients = silc_client_get_clients_local(sg->client, sg->conn,
-						nickname, name,
-						&clients_count);
+						name, FALSE);
 	if (!clients) {
-		silc_client_get_clients(sg->client, sg->conn, nickname, NULL,
+		silc_client_get_clients(sg->client, sg->conn, name, NULL,
 					silcpurple_buddy_privkey_resolved,
 					g_strdup(name));
-		silc_free(nickname);
 		return;
 	}
 
+	silc_dlist_start(clients);
+	client_entry = silc_dlist_get(clients);
+
 	p = silc_calloc(1, sizeof(*p));
 	if (!p)
 		return;
 	p->client = sg->client;
 	p->conn = sg->conn;
-	p->client_id = *clients[0]->id;
+	p->client_id = client_entry->id;
 	purple_request_input(gc, _("IM With Password"), NULL,
 	                     _("Set IM Password"), NULL, FALSE, TRUE, NULL,
 	                     _("OK"), G_CALLBACK(silcpurple_buddy_privkey_cb),
 	                     _("Cancel"), G_CALLBACK(silcpurple_buddy_privkey_cb),
 	                     gc->account, NULL, NULL, p);
 
-	silc_free(clients);
-	silc_free(nickname);
+	silc_client_list_free(sg->client, sg->conn, clients);
 }
 
 static void
@@ -498,13 +484,21 @@
 static void
 silcpurple_buddy_getkey(PurpleConnection *gc, const char *name);
 
-static void
-silcpurple_buddy_getkey_cb(SilcPurpleBuddyGetkey g,
-			 SilcClientCommandReplyContext cmd)
+static SilcBool
+silcpurple_buddy_getkey_cb(SilcClient client, SilcClientConnection conn,
+			   SilcCommand command, SilcStatus status,
+			   SilcStatus error, void *context, va_list ap)
 {
 	SilcClientEntry client_entry;
-	unsigned char *pk;
-	SilcUInt32 pk_len;
+	SilcPurpleBuddyGetkey g = context;
+
+	if (status != SILC_STATUS_OK) {
+		purple_notify_error(g->client->application, _("Get Public Key"),
+				  _("The remote user is not present in the network any more"),
+				  NULL);
+		silc_free(g);
+		return FALSE;
+	}
 
 	/* Get the client entry. */
 	client_entry = silc_client_get_client_by_id(g->client, g->conn,
@@ -514,30 +508,28 @@
 				  _("The remote user is not present in the network any more"),
 				  NULL);
 		silc_free(g);
-		return;
+		return FALSE;
 	}
 
 	if (!client_entry->public_key) {
 		silc_free(g);
-		return;
+		return FALSE;
 	}
 
 	/* Now verify the public key */
-	pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len);
 	silcpurple_verify_public_key(g->client, g->conn, client_entry->nickname,
-				   SILC_SOCKET_TYPE_CLIENT,
-				   pk, pk_len, SILC_SKE_PK_TYPE_SILC,
-				   NULL, NULL);
-	silc_free(pk);
+				     SILC_CONN_CLIENT, client_entry->public_key,
+				     NULL, NULL);
 	silc_free(g);
+	return TRUE;
 }
 
 static void
 silcpurple_buddy_getkey_resolved(SilcClient client,
-			       SilcClientConnection conn,
-			       SilcClientEntry *clients,
-			       SilcUInt32 clients_count,
-			       void *context)
+				 SilcClientConnection conn,
+				 SilcStatus status,
+				 SilcDList clients,
+				 void *context)
 {
 	char tmp[256];
 
@@ -546,7 +538,7 @@
 			   _("User %s is not present in the network"),
 			   (const char *)context);
 		purple_notify_error(client->application, _("Get Public Key"),
-				  _("Cannot fetch the public key"), tmp);
+				    _("Cannot fetch the public key"), tmp);
 		g_free(context);
 		return;
 	}
@@ -561,42 +553,38 @@
 	SilcPurple sg = gc->proto_data;
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
-	SilcClientEntry *clients;
-	SilcUInt32 clients_count;
+	SilcClientEntry client_entry;
+	SilcDList clients;
 	SilcPurpleBuddyGetkey g;
-	char *nickname;
+	SilcUInt16 cmd_ident;
 
 	if (!name)
 		return;
 
-	if (!silc_parse_userfqdn(name, &nickname, NULL))
-		return;
-
 	/* Find client entry */
-	clients = silc_client_get_clients_local(client, conn, nickname, name,
-						&clients_count);
+	clients = silc_client_get_clients_local(client, conn, name, FALSE);
 	if (!clients) {
-		silc_client_get_clients(client, conn, nickname, NULL,
+		silc_client_get_clients(client, conn, name, NULL,
 					silcpurple_buddy_getkey_resolved,
 					g_strdup(name));
-		silc_free(nickname);
 		return;
 	}
 
+	silc_dlist_start(clients);
+	client_entry = silc_dlist_get(clients);
+
 	/* Call GETKEY */
 	g = silc_calloc(1, sizeof(*g));
 	if (!g)
 		return;
 	g->client = client;
 	g->conn = conn;
-	g->client_id = *clients[0]->id;
-	silc_client_command_call(client, conn, NULL, "GETKEY",
-				 clients[0]->nickname, NULL);
-	silc_client_command_pending(conn, SILC_COMMAND_GETKEY,
-				    conn->cmd_ident,
-				    (SilcCommandCb)silcpurple_buddy_getkey_cb, g);
-	silc_free(clients);
-	silc_free(nickname);
+	g->client_id = client_entry->id;
+	cmd_ident = silc_client_command_call(client, conn, NULL, "GETKEY",
+					     client_entry->nickname, NULL);
+	silc_client_command_pending(conn, SILC_COMMAND_GETKEY, cmd_ident,
+				    silcpurple_buddy_getkey_cb, g);
+	silc_client_list_free(client, conn, clients);
 }
 
 static void
@@ -629,8 +617,7 @@
 	sg = gc->proto_data;
 
 	pkfile = purple_blist_node_get_string(node, "public-key");
-	if (!silc_pkcs_load_public_key(pkfile, &public_key, SILC_PKCS_FILE_PEM) &&
-	    !silc_pkcs_load_public_key(pkfile, &public_key, SILC_PKCS_FILE_BIN)) {
+	if (!silc_pkcs_load_public_key(pkfile, &public_key)) {
 		purple_notify_error(gc,
 				  _("Show Public Key"),
 				  _("Could not load public key"), NULL);
@@ -661,6 +648,7 @@
 	PurpleBuddy *b;
 	unsigned char *offline_pk;
 	SilcUInt32 offline_pk_len;
+	SilcPublicKey public_key;
 	unsigned int offline        : 1;
 	unsigned int pubkey_search  : 1;
 	unsigned int init           : 1;
@@ -670,10 +658,10 @@
 silcpurple_add_buddy_ask_pk_cb(SilcPurpleBuddyRes r, gint id);
 static void
 silcpurple_add_buddy_resolved(SilcClient client,
-			    SilcClientConnection conn,
-			    SilcClientEntry *clients,
-			    SilcUInt32 clients_count,
-			    void *context);
+			      SilcClientConnection conn,
+			      SilcStatus status,
+			      SilcDList clients,
+			      void *context);
 
 void silcpurple_get_info(PurpleConnection *gc, const char *who)
 {
@@ -735,35 +723,36 @@
 	g_snprintf(tmp, sizeof(tmp), _("The %s buddy is not trusted"),
 		   r->b->name);
 	purple_notify_error(r->client->application, _("Add Buddy"), tmp,
-			  _("You cannot receive buddy notifications until you "
-			    "import his/her public key.  You can use the Get Public Key "
-			    "command to get the public key."));
+			    _("You cannot receive buddy notifications until you "
+			      "import his/her public key.  You can use the Get Public Key "
+			      "command to get the public key."));
 	purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
 }
 
 static void
-silcpurple_add_buddy_save(bool success, void *context)
+silcpurple_add_buddy_save(SilcBool success, void *context)
 {
 	SilcPurpleBuddyRes r = context;
 	PurpleBuddy *b = r->b;
-	SilcClient client = r->client;
 	SilcClientEntry client_entry;
 	SilcAttributePayload attr;
 	SilcAttribute attribute;
 	SilcVCardStruct vcard;
-	SilcAttributeObjMime message, extension;
-#ifdef SILC_ATTRIBUTE_USER_ICON
-	SilcAttributeObjMime usericon;
-#endif
+	SilcMime message = NULL, extension = NULL;
+	SilcMime usericon = NULL;
 	SilcAttributeObjPk serverpk, usersign, serversign;
 	gboolean usign_success = TRUE, ssign_success = TRUE;
 	char filename[512], filename2[512], *fingerprint = NULL, *tmp;
 	SilcUInt32 len;
+	SilcHash hash;
 	int i;
 
 	if (!success) {
 		/* The user did not trust the public key. */
 		silcpurple_add_buddy_pk_no(r);
+		silc_free(r->offline_pk);
+		if (r->public_key)
+		  silc_pkcs_public_key_free(r->public_key);
 		silc_free(r);
 		return;
 	}
@@ -783,6 +772,8 @@
 		purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
 		silc_free(fingerprint);
 		silc_free(r->offline_pk);
+		if (r->public_key)
+		  silc_pkcs_public_key_free(r->public_key);
 		silc_free(r);
 		return;
 	}
@@ -791,16 +782,15 @@
 	client_entry = silc_client_get_client_by_id(r->client, r->conn,
 						    &r->client_id);
 	if (!client_entry) {
+		silc_free(r->offline_pk);
+		silc_pkcs_public_key_free(r->public_key);
+		if (r->public_key)
+		  silc_pkcs_public_key_free(r->public_key);
 		silc_free(r);
 		return;
 	}
 
 	memset(&vcard, 0, sizeof(vcard));
-	memset(&message, 0, sizeof(message));
-	memset(&extension, 0, sizeof(extension));
-#ifdef SILC_ATTRIBUTE_USER_ICON
-	memset(&usericon, 0, sizeof(usericon));
-#endif
 	memset(&serverpk, 0, sizeof(serverpk));
 	memset(&usersign, 0, sizeof(usersign));
 	memset(&serversign, 0, sizeof(serversign));
@@ -822,24 +812,25 @@
 				break;
 
 			case SILC_ATTRIBUTE_STATUS_MESSAGE:
-				if (!silc_attribute_get_object(attr, (void *)&message,
-							       sizeof(message)))
+				message = silc_mime_alloc();
+				if (!silc_attribute_get_object(attr, (void *)message,
+							       sizeof(*message)))
 					continue;
 				break;
 
 			case SILC_ATTRIBUTE_EXTENSION:
-				if (!silc_attribute_get_object(attr, (void *)&extension,
-							       sizeof(extension)))
+				extension = silc_mime_alloc();
+				if (!silc_attribute_get_object(attr, (void *)extension,
+							       sizeof(*extension)))
 					continue;
 				break;
 
-#ifdef SILC_ATTRIBUTE_USER_ICON
 			case SILC_ATTRIBUTE_USER_ICON:
-				if (!silc_attribute_get_object(attr, (void *)&usericon,
-							       sizeof(usericon)))
+				usericon = silc_mime_alloc();
+				if (!silc_attribute_get_object(attr, (void *)usericon,
+							       sizeof(*usericon)))
 					continue;
 				break;
-#endif
 
 			case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY:
 				if (serverpk.type)
@@ -872,50 +863,54 @@
 	}
 
 	/* Verify the attribute signatures */
+	silc_hash_alloc((const unsigned char *)"sha1", &hash);
 
 	if (usersign.data) {
-		SilcPKCS pkcs;
 		unsigned char *verifyd;
 		SilcUInt32 verify_len;
 
-		silc_pkcs_alloc((unsigned char*)"rsa", &pkcs);
 		verifyd = silc_attribute_get_verify_data(client_entry->attrs,
 							 FALSE, &verify_len);
-		if (verifyd && silc_pkcs_public_key_set(pkcs, client_entry->public_key)){
-			if (!silc_pkcs_verify_with_hash(pkcs, client->sha1hash,
-							usersign.data,
-							usersign.data_len,
-							verifyd, verify_len))
-				usign_success = FALSE;
-		}
+		if (verifyd && !silc_pkcs_verify(client_entry->public_key,
+						 usersign.data,
+						 usersign.data_len,
+						 verifyd, verify_len, hash))
+			usign_success = FALSE;
 		silc_free(verifyd);
 	}
 
-	if (serversign.data && !strcmp(serverpk.type, "silc-rsa")) {
+	if (serversign.data) {
 		SilcPublicKey public_key;
-		SilcPKCS pkcs;
+		SilcPKCSType type = 0;
 		unsigned char *verifyd;
 		SilcUInt32 verify_len;
 
-		if (silc_pkcs_public_key_decode(serverpk.data, serverpk.data_len,
-						&public_key)) {
-			silc_pkcs_alloc((unsigned char *)"rsa", &pkcs);
+		if (!strcmp(serverpk.type, "silc-rsa"))
+		  type = SILC_PKCS_SILC;
+		else if (!strcmp(serverpk.type, "ssh-rsa"))
+		  type = SILC_PKCS_SSH2;
+		else if (!strcmp(serverpk.type, "x509v3-sign-rsa"))
+		  type = SILC_PKCS_X509V3;
+		else if (!strcmp(serverpk.type, "pgp-sign-rsa"))
+		  type = SILC_PKCS_OPENPGP;
+
+		if (silc_pkcs_public_key_alloc(type, serverpk.data,
+					       serverpk.data_len,
+					       &public_key)) {
 			verifyd = silc_attribute_get_verify_data(client_entry->attrs,
 								 TRUE, &verify_len);
-			if (verifyd && silc_pkcs_public_key_set(pkcs, public_key)) {
-				if (!silc_pkcs_verify_with_hash(pkcs, client->sha1hash,
-							       serversign.data,
-							       serversign.data_len,
-							       verifyd, verify_len))
-					ssign_success = FALSE;
-			}
+			if (verifyd && !silc_pkcs_verify(public_key,
+							 serversign.data,
+							 serversign.data_len,
+							 verifyd, verify_len,
+							 hash))
+				ssign_success = FALSE;
 			silc_pkcs_public_key_free(public_key);
 			silc_free(verifyd);
 		}
 	}
 
-	fingerprint = silc_fingerprint(client_entry->fingerprint,
-				       client_entry->fingerprint_len);
+	fingerprint = silc_fingerprint(client_entry->fingerprint, 20);
 	for (i = 0; i < strlen(fingerprint); i++)
 		if (fingerprint[i] == ' ')
 			fingerprint[i] = '_';
@@ -954,48 +949,45 @@
 		}
 
 		/* Save status message */
-		if (message.mime) {
+		if (message) {
 			memset(filename2, 0, sizeof(filename2));
 			g_snprintf(filename2, sizeof(filename2) - 1,
 				   "%s" G_DIR_SEPARATOR_S "status_message.mime",
 				   filename);
-			silc_file_writefile(filename2, (char *)message.mime,
-					    message.mime_len);
+			tmp = (char *)silc_mime_get_data(message, &len);
+			silc_file_writefile(filename2, tmp, len);
+			silc_mime_free(message);
 		}
 
 		/* Save extension data */
-		if (extension.mime) {
+		if (extension) {
 			memset(filename2, 0, sizeof(filename2));
 			g_snprintf(filename2, sizeof(filename2) - 1,
 				   "%s" G_DIR_SEPARATOR_S "extension.mime",
 				   filename);
-			silc_file_writefile(filename2, (char *)extension.mime,
-					    extension.mime_len);
+			tmp = (char *)silc_mime_get_data(extension, &len);
+			silc_file_writefile(filename2, tmp, len);
+			silc_mime_free(extension);
 		}
 
-#ifdef SILC_ATTRIBUTE_USER_ICON
 		/* Save user icon */
-		if (usericon.mime) {
-			SilcMime m = silc_mime_decode(usericon.mime,
-						      usericon.mime_len);
-			if (m) {
-				const char *type = silc_mime_get_field(m, "Content-Type");
-				if (!strcmp(type, "image/jpeg") ||
-				    !strcmp(type, "image/gif") ||
-				    !strcmp(type, "image/bmp") ||
-				    !strcmp(type, "image/png")) {
-					const unsigned char *data;
-					SilcUInt32 data_len;
-					data = silc_mime_get_data(m, &data_len);
-					if (data) {
-						/* TODO: Check if SILC gives us something to use as the checksum instead */
-						purple_buddy_icons_set_for_user(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), g_memdup(data, data_len), data_len, NULL);
-					}
+		if (usericon) {
+			const char *type = silc_mime_get_field(usericon, "Content-Type");
+			if (type &&
+			    (!strcmp(type, "image/jpeg") ||
+			     !strcmp(type, "image/gif") ||
+			     !strcmp(type, "image/bmp") ||
+			     !strcmp(type, "image/png"))) {
+				const unsigned char *data;
+				SilcUInt32 data_len;
+				data = silc_mime_get_data(usericon, &data_len);
+				if (data) {
+					/* TODO: Check if SILC gives us something to use as the checksum instead */
+					purple_buddy_icons_set_for_user(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), g_memdup(data, data_len), data_len, NULL);
 				}
-				silc_mime_free(m);
 			}
+			silc_mime_free(usericon);
 		}
-#endif
 	}
 
 	/* Save the public key path to buddy properties, as it is used
@@ -1015,7 +1007,11 @@
 	silc_client_command_call(r->client, r->conn, NULL, "WATCH", "-pubkey",
 				 filename2, NULL);
 
+	silc_hash_free(hash);
 	silc_free(fingerprint);
+	silc_free(r->offline_pk);
+	if (r->public_key)
+	  silc_pkcs_public_key_free(r->public_key);
 	silc_free(r);
 }
 
@@ -1023,11 +1019,9 @@
 silcpurple_add_buddy_ask_import(void *user_data, const char *name)
 {
 	SilcPurpleBuddyRes r = (SilcPurpleBuddyRes)user_data;
-	SilcPublicKey public_key;
 
 	/* Load the public key */
-	if (!silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_PEM) &&
-	    !silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_BIN)) {
+	if (!silc_pkcs_load_public_key(name, &r->public_key)) {
 		silcpurple_add_buddy_ask_pk_cb(r, 0);
 		purple_notify_error(r->client->application,
 				  _("Add Buddy"), _("Could not load public key"), NULL);
@@ -1035,12 +1029,10 @@
 	}
 
 	/* Now verify the public key */
-	r->offline_pk = silc_pkcs_public_key_encode(public_key, &r->offline_pk_len);
+	r->offline_pk = silc_pkcs_public_key_encode(r->public_key, &r->offline_pk_len);
 	silcpurple_verify_public_key(r->client, r->conn, r->b->name,
-				   SILC_SOCKET_TYPE_CLIENT,
-				   r->offline_pk, r->offline_pk_len,
-				   SILC_SKE_PK_TYPE_SILC,
-				   silcpurple_add_buddy_save, r);
+				     SILC_CONN_CLIENT, r->public_key,
+				     silcpurple_add_buddy_save, r);
 }
 
 static void
@@ -1065,9 +1057,9 @@
 
 	/* Open file selector to select the public key. */
 	purple_request_file(r->client->application, _("Open..."), NULL, FALSE,
-			  G_CALLBACK(silcpurple_add_buddy_ask_import),
-			  G_CALLBACK(silcpurple_add_buddy_ask_pk_cancel),
-			  purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r);
+			    G_CALLBACK(silcpurple_add_buddy_ask_import),
+			    G_CALLBACK(silcpurple_add_buddy_ask_pk_cancel),
+			    purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r);
 
 }
 
@@ -1078,20 +1070,29 @@
 	g_snprintf(tmp, sizeof(tmp), _("The %s buddy is not present in the network"),
 		   r->b->name);
 	purple_request_action(r->client->application, _("Add Buddy"), tmp,
-			    _("To add the buddy you must import his/her public key. "
-			      "Press Import to import a public key."), 0,
-				  purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r, 2,
-			    _("Cancel"), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb),
-			    _("_Import..."), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb));
+			      _("To add the buddy you must import his/her public key. "
+				"Press Import to import a public key."), 0,
+			      purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r, 2,
+			      _("Cancel"), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb),
+			      _("_Import..."), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb));
 }
 
-static void
-silcpurple_add_buddy_getkey_cb(SilcPurpleBuddyRes r,
-			     SilcClientCommandReplyContext cmd)
+static SilcBool
+silcpurple_add_buddy_getkey_cb(SilcClient client, SilcClientConnection conn,
+			       SilcCommand command, SilcStatus status,
+			       SilcStatus error, void *context, va_list ap)
 {
+	SilcPurpleBuddyRes r = context;
 	SilcClientEntry client_entry;
-	unsigned char *pk;
-	SilcUInt32 pk_len;
+
+	if (status != SILC_STATUS_OK) {
+		/* The buddy is offline/nonexistent. We will require user
+		   to associate a public key with the buddy or the buddy
+		   cannot be added. */
+		r->offline = TRUE;
+		silcpurple_add_buddy_ask_pk(r);
+		return FALSE;
+	}
 
 	/* Get the client entry. */
 	client_entry = silc_client_get_client_by_id(r->client, r->conn,
@@ -1102,16 +1103,14 @@
 		   cannot be added. */
 		r->offline = TRUE;
 		silcpurple_add_buddy_ask_pk(r);
-		return;
+		return FALSE;
 	}
 
 	/* Now verify the public key */
-	pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len);
 	silcpurple_verify_public_key(r->client, r->conn, client_entry->nickname,
-				   SILC_SOCKET_TYPE_CLIENT,
-				   pk, pk_len, SILC_SKE_PK_TYPE_SILC,
-				   silcpurple_add_buddy_save, r);
-	silc_free(pk);
+				     SILC_CONN_CLIENT, client_entry->public_key,
+				     silcpurple_add_buddy_save, r);
+	return TRUE;
 }
 
 static void
@@ -1120,6 +1119,7 @@
 	PurpleRequestField *f;
 	const GList *list;
 	SilcClientEntry client_entry;
+	SilcDList clients;
 
 	f = purple_request_fields_get_field(fields, "list");
 	list = purple_request_field_list_get_selected(f);
@@ -1131,7 +1131,11 @@
 	}
 
 	client_entry = purple_request_field_list_get_data(f, list->data);
-	silcpurple_add_buddy_resolved(r->client, r->conn, &client_entry, 1, r);
+	clients = silc_dlist_init();
+	silc_dlist_add(clients, client_entry);
+	silcpurple_add_buddy_resolved(r->client, r->conn, SILC_STATUS_OK,
+				      clients, r);
+	silc_dlist_uninit(clients);
 }
 
 static void
@@ -1143,16 +1147,14 @@
 }
 
 static void
-silcpurple_add_buddy_select(SilcPurpleBuddyRes r,
-			  SilcClientEntry *clients,
-			  SilcUInt32 clients_count)
+silcpurple_add_buddy_select(SilcPurpleBuddyRes r, SilcDList clients)
 {
 	PurpleRequestFields *fields;
 	PurpleRequestFieldGroup *g;
 	PurpleRequestField *f;
 	char tmp[512], tmp2[128];
-	int i;
 	char *fingerprint;
+	SilcClientEntry client_entry;
 
 	fields = purple_request_fields_new();
 	g = purple_request_field_group_new(NULL);
@@ -1161,56 +1163,56 @@
 	purple_request_field_list_set_multi_select(f, FALSE);
 	purple_request_fields_add_group(fields, g);
 
-	for (i = 0; i < clients_count; i++) {
+	silc_dlist_start(clients);
+	while ((client_entry = silc_dlist_get(clients))) {
 		fingerprint = NULL;
-		if (clients[i]->fingerprint) {
-			fingerprint = silc_fingerprint(clients[i]->fingerprint,
-						       clients[i]->fingerprint_len);
+		if (*client_entry->fingerprint) {
+			fingerprint = silc_fingerprint(client_entry->fingerprint, 20);
 			g_snprintf(tmp2, sizeof(tmp2), "\n%s", fingerprint);
 		}
 		g_snprintf(tmp, sizeof(tmp), "%s - %s (%s@%s)%s",
-			   clients[i]->realname, clients[i]->nickname,
-			   clients[i]->username, clients[i]->hostname ?
-			   clients[i]->hostname : "",
+			   client_entry->realname, client_entry->nickname,
+			   client_entry->username, *client_entry->hostname ?
+			   client_entry->hostname : "",
 			   fingerprint ? tmp2 : "");
-		purple_request_field_list_add(f, tmp, clients[i]);
+		purple_request_field_list_add(f, tmp, client_entry);
 		silc_free(fingerprint);
 	}
 
 	purple_request_fields(r->client->application, _("Add Buddy"),
-				_("Select correct user"),
-				r->pubkey_search
-					? _("More than one user was found with the same public key. Select "
-						"the correct user from the list to add to the buddy list.")
-					: _("More than one user was found with the same name. Select "
-						"the correct user from the list to add to the buddy list."),
-				fields,
-				_("OK"), G_CALLBACK(silcpurple_add_buddy_select_cb),
-				_("Cancel"), G_CALLBACK(silcpurple_add_buddy_select_cancel),
-				purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r);
+			      _("Select correct user"),
+			      r->pubkey_search
+			      ? _("More than one user was found with the same public key. Select "
+				  "the correct user from the list to add to the buddy list.")
+			      : _("More than one user was found with the same name. Select "
+				  "the correct user from the list to add to the buddy list."),
+			      fields,
+			      _("OK"), G_CALLBACK(silcpurple_add_buddy_select_cb),
+			      _("Cancel"), G_CALLBACK(silcpurple_add_buddy_select_cancel),
+			      purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r);
 }
 
 static void
 silcpurple_add_buddy_resolved(SilcClient client,
-			    SilcClientConnection conn,
-			    SilcClientEntry *clients,
-			    SilcUInt32 clients_count,
-			    void *context)
+			      SilcClientConnection conn,
+			      SilcStatus status,
+			      SilcDList clients,
+			      void *context)
 {
 	SilcPurpleBuddyRes r = context;
 	PurpleBuddy *b = r->b;
 	SilcAttributePayload pub;
 	SilcAttributeObjPk userpk;
-	unsigned char *pk;
-	SilcUInt32 pk_len;
 	const char *filename;
+	SilcClientEntry client_entry = NULL;
+	SilcUInt16 cmd_ident;
 
 	filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key");
 
 	/* If the buddy is offline/nonexistent, we will require user
 	   to associate a public key with the buddy or the buddy
 	   cannot be added. */
-	if (!clients_count) {
+	if (!clients) {
 		if (r->init) {
 			silc_free(r);
 			return;
@@ -1228,33 +1230,37 @@
 
 	/* If more than one client was found with nickname, we need to verify
 	   from user which one is the correct. */
-	if (clients_count > 1 && !r->pubkey_search) {
+	if (silc_dlist_count(clients) > 1 && !r->pubkey_search) {
 		if (r->init) {
 			silc_free(r);
 			return;
 		}
 
-		silcpurple_add_buddy_select(r, clients, clients_count);
+		silcpurple_add_buddy_select(r, clients);
 		return;
 	}
 
+	silc_dlist_start(clients);
+	client_entry = silc_dlist_get(clients);
+
 	/* If we searched using public keys and more than one entry was found
 	   the same person is logged on multiple times. */
-	if (clients_count > 1 && r->pubkey_search && b->name) {
+	if (silc_dlist_count(clients) > 1 && r->pubkey_search && b->name) {
 		if (r->init) {
 			/* Find the entry that closest matches to the
 			   buddy nickname. */
-			int i;
-			for (i = 0; i < clients_count; i++) {
-				if (!strncasecmp(b->name, clients[i]->nickname,
+			SilcClientEntry entry;
+			silc_dlist_start(clients);
+			while ((entry = silc_dlist_get(clients))) {
+				if (!strncasecmp(b->name, entry->nickname,
 						 strlen(b->name))) {
-					clients[0] = clients[i];
+					client_entry = entry;
 					break;
 				}
 			}
 		} else {
 			/* Verify from user which one is correct */
-			silcpurple_add_buddy_select(r, clients, clients_count);
+			silcpurple_add_buddy_select(r, clients);
 			return;
 		}
 	}
@@ -1262,61 +1268,60 @@
 	/* The client was found.  Now get its public key and verify
 	   that before adding the buddy. */
 	memset(&userpk, 0, sizeof(userpk));
-	b->proto_data = silc_memdup(clients[0]->id, sizeof(*clients[0]->id));
-	r->client_id = *clients[0]->id;
+	b->proto_data = silc_memdup(&client_entry->id, sizeof(client_entry->id));
+	r->client_id = client_entry->id;
 
 	/* Get the public key from attributes, if not present then
 	   resolve it with GETKEY unless we have it cached already. */
-	if (clients[0]->attrs && !clients[0]->public_key) {
-		pub = silcpurple_get_attr(clients[0]->attrs,
-					SILC_ATTRIBUTE_USER_PUBLIC_KEY);
+	if (client_entry->attrs && !client_entry->public_key) {
+		pub = silcpurple_get_attr(client_entry->attrs,
+					  SILC_ATTRIBUTE_USER_PUBLIC_KEY);
 		if (!pub || !silc_attribute_get_object(pub, (void *)&userpk,
 						       sizeof(userpk))) {
 			/* Get public key with GETKEY */
-			silc_client_command_call(client, conn, NULL,
-						 "GETKEY", clients[0]->nickname, NULL);
+			cmd_ident =
+			  silc_client_command_call(client, conn, NULL,
+						   "GETKEY", client_entry->nickname, NULL);
 			silc_client_command_pending(conn, SILC_COMMAND_GETKEY,
-						    conn->cmd_ident,
-						    (SilcCommandCb)silcpurple_add_buddy_getkey_cb,
+						    cmd_ident,
+						    silcpurple_add_buddy_getkey_cb,
 						    r);
 			return;
 		}
-		if (!silc_pkcs_public_key_decode(userpk.data, userpk.data_len,
-						 &clients[0]->public_key))
+		if (!silc_pkcs_public_key_alloc(SILC_PKCS_SILC,
+						userpk.data, userpk.data_len,
+						&client_entry->public_key))
 			return;
 		silc_free(userpk.data);
-	} else if (filename && !clients[0]->public_key) {
-		if (!silc_pkcs_load_public_key(filename, &clients[0]->public_key,
-					       SILC_PKCS_FILE_PEM) &&
-		    !silc_pkcs_load_public_key(filename, &clients[0]->public_key,
-					       SILC_PKCS_FILE_BIN)) {
+	} else if (filename && !client_entry->public_key) {
+		if (!silc_pkcs_load_public_key(filename, &client_entry->public_key)) {
 			/* Get public key with GETKEY */
-			silc_client_command_call(client, conn, NULL,
-						 "GETKEY", clients[0]->nickname, NULL);
+			cmd_ident =
+			  silc_client_command_call(client, conn, NULL,
+						   "GETKEY", client_entry->nickname, NULL);
 			silc_client_command_pending(conn, SILC_COMMAND_GETKEY,
-						    conn->cmd_ident,
-						    (SilcCommandCb)silcpurple_add_buddy_getkey_cb,
+						    cmd_ident,
+						    silcpurple_add_buddy_getkey_cb,
 						    r);
 			return;
 		}
-	} else if (!clients[0]->public_key) {
+	} else if (!client_entry->public_key) {
 		/* Get public key with GETKEY */
-		silc_client_command_call(client, conn, NULL,
-					 "GETKEY", clients[0]->nickname, NULL);
+		cmd_ident =
+		  silc_client_command_call(client, conn, NULL,
+					   "GETKEY", client_entry->nickname, NULL);
 		silc_client_command_pending(conn, SILC_COMMAND_GETKEY,
-					    conn->cmd_ident,
-					    (SilcCommandCb)silcpurple_add_buddy_getkey_cb,
+					    cmd_ident,
+					    silcpurple_add_buddy_getkey_cb,
 					    r);
 		return;
 	}
 
 	/* We have the public key, verify it. */
-	pk = silc_pkcs_public_key_encode(clients[0]->public_key, &pk_len);
-	silcpurple_verify_public_key(client, conn, clients[0]->nickname,
-				   SILC_SOCKET_TYPE_CLIENT,
-				   pk, pk_len, SILC_SKE_PK_TYPE_SILC,
-				   silcpurple_add_buddy_save, r);
-	silc_free(pk);
+	silcpurple_verify_public_key(client, conn, client_entry->nickname,
+				     SILC_CONN_CLIENT,
+				     client_entry->public_key,
+				     silcpurple_add_buddy_save, r);
 }
 
 static void
@@ -1344,10 +1349,7 @@
 		SilcPublicKey public_key;
 		SilcAttributeObjPk userpk;
 
-		if (!silc_pkcs_load_public_key(filename, &public_key,
-					       SILC_PKCS_FILE_PEM) &&
-		    !silc_pkcs_load_public_key(filename, &public_key,
-					       SILC_PKCS_FILE_BIN))
+		if (!silc_pkcs_load_public_key(filename, &public_key))
 			return;
 
 		/* Get all attributes, and use the public key to search user */
@@ -1361,9 +1363,7 @@
 						       SILC_ATTRIBUTE_PREFERRED_CONTACT,
 						       SILC_ATTRIBUTE_TIMEZONE,
 						       SILC_ATTRIBUTE_GEOLOCATION,
-#ifdef SILC_ATTRIBUTE_USER_ICON
 						       SILC_ATTRIBUTE_USER_ICON,
-#endif
 						       SILC_ATTRIBUTE_DEVICE_INFO, 0);
 		userpk.type = "silc-rsa";
 		userpk.data = silc_pkcs_public_key_encode(public_key, &userpk.data_len);
@@ -1632,12 +1632,13 @@
 						    sg->conn,
 						    buddy->proto_data);
 
-	if (client_entry && client_entry->send_key) {
+	if (client_entry &&
+	    silc_client_private_message_key_is_set(sg->client,
+						   sg->conn, client_entry)) {
 		act = purple_menu_action_new(_("Reset IM Key"),
 		                           PURPLE_CALLBACK(silcpurple_buddy_resetkey),
 		                           NULL, NULL);
 		m = g_list_append(m, act);
-
 	} else {
 		act = purple_menu_action_new(_("IM with Key Exchange"),
 		                           PURPLE_CALLBACK(silcpurple_buddy_keyagr),
@@ -1682,7 +1683,6 @@
 	return m;
 }
 
-#ifdef SILC_ATTRIBUTE_USER_ICON
 void silcpurple_buddy_set_icon(PurpleConnection *gc, PurpleStoredImage *img)
 {
 	SilcPurple sg = gc->proto_data;
@@ -1690,9 +1690,7 @@
 	SilcClientConnection conn = sg->conn;
 	SilcMime mime;
 	char type[32];
-	unsigned char *icon;
 	const char *t;
-	SilcAttributeObjMime obj;
 
 	/* Remove */
 	if (!img) {
@@ -1717,12 +1715,8 @@
 	silc_mime_add_field(mime, "Content-Type", type);
 	silc_mime_add_data(mime, purple_imgstore_get_data(img), purple_imgstore_get_size(img));
 
-	obj.mime = icon = silc_mime_encode(mime, &obj.mime_len);
-	if (obj.mime)
-		silc_client_attribute_add(client, conn, 
-					  SILC_ATTRIBUTE_USER_ICON, &obj, sizeof(obj));
+	silc_client_attribute_add(client, conn,
+				  SILC_ATTRIBUTE_USER_ICON, mime, sizeof(*mime));
 
-	silc_free(icon);
 	silc_mime_free(mime);
 }
-#endif
--- a/libpurple/protocols/silc/chat.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/silc/chat.c	Mon Jun 18 01:48:35 2007 +0000
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2004 Pekka Riikonen
+  Copyright (C) 2004 - 2007 Pekka Riikonen
 
   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
@@ -17,7 +17,7 @@
 
 */
 
-#include "silcincludes.h"
+#include "silc.h"
 #include "silcclient.h"
 #include "silcpurple.h"
 #include "wb.h"
@@ -61,10 +61,10 @@
 
 static void
 silcpurple_chat_getinfo_res(SilcClient client,
-			  SilcClientConnection conn,
-			  SilcChannelEntry *channels,
-			  SilcUInt32 channels_count,
-			  void *context)
+			    SilcClientConnection conn,
+			    SilcStatus status,
+			    SilcDList channels,
+			    void *context)
 {
 	GHashTable *components = context;
 	PurpleConnection *gc = client->application;
@@ -134,13 +134,14 @@
 	}
 	silc_hash_table_list_reset(&htl);
 
-	if (channel->channel_key)
+	if (channel->cipher)
 		g_string_append_printf(s, _("<br><b>Channel Cipher:</b> %s"),
-				       silc_cipher_get_name(channel->channel_key));
+				       channel->cipher);
+
 	if (channel->hmac)
 		/* Definition of HMAC: http://en.wikipedia.org/wiki/HMAC */
 		g_string_append_printf(s, _("<br><b>Channel HMAC:</b> %s"),
-				       silc_hmac_get_name(channel->hmac));
+				       channel->hmac);
 
 	if (channel->topic) {
 		tmp2 = g_markup_escape_text(channel->topic, -1);
@@ -211,7 +212,7 @@
 	SilcPurple sg;
 	SilcChannelEntry channel;
 	PurpleChat *c;
-	SilcBuffer pubkeys;
+	SilcDList pubkeys;
 } *SilcPurpleChauth;
 
 static void
@@ -227,22 +228,21 @@
 	SilcUInt32 m;
 
 	/* Load the public key */
-	if (!silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_PEM) &&
-	    !silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_BIN)) {
+	if (!silc_pkcs_load_public_key(name, &public_key)) {
 		silcpurple_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys);
-		silc_buffer_free(sgc->pubkeys);
+		silc_dlist_uninit(sgc->pubkeys);
 		silc_free(sgc);
 		purple_notify_error(client->application,
-				  _("Add Channel Public Key"),
-				  _("Could not load public key"), NULL);
+				    _("Add Channel Public Key"),
+				    _("Could not load public key"), NULL);
 		return;
 	}
 
-	pk = silc_pkcs_public_key_payload_encode(public_key);
+	pk = silc_public_key_payload_encode(public_key);
 	chpks = silc_buffer_alloc_size(2);
 	SILC_PUT16_MSB(1, chpks->head);
 	chpks = silc_argument_payload_encode_one(chpks, pk->data,
-						 pk->len, 0x00);
+						 silc_buffer_len(pk), 0x00);
 	silc_buffer_free(pk);
 
 	m = sgc->channel->mode;
@@ -250,15 +250,20 @@
 
 	/* Send CMODE */
 	SILC_PUT32_MSB(m, mode);
-	chidp = silc_id_payload_encode(sgc->channel->id, SILC_ID_CHANNEL);
+	chidp = silc_id_payload_encode(&sgc->channel->id, SILC_ID_CHANNEL);
 	silc_client_command_send(client, conn, SILC_COMMAND_CMODE,
-				 ++conn->cmd_ident, 3,
-				 1, chidp->data, chidp->len,
+				 silcpurple_command_reply, NULL, 3,
+				 1, chidp->data, silc_buffer_len(chidp),
 				 2, mode, sizeof(mode),
-				 9, chpks->data, chpks->len);
+				 9, chpks->data, silc_buffer_len(chpks));
 	silc_buffer_free(chpks);
 	silc_buffer_free(chidp);
-	silc_buffer_free(sgc->pubkeys);
+	if (sgc->pubkeys) {
+	  silc_dlist_start(sgc->pubkeys);
+	  while ((public_key = silc_dlist_get(sgc->pubkeys)))
+		silc_pkcs_public_key_free(public_key);
+	  silc_dlist_uninit(sgc->pubkeys);
+	}
 	silc_free(sgc);
 }
 
@@ -266,8 +271,16 @@
 silcpurple_chat_chpk_cancel(void *user_data, const char *name)
 {
 	SilcPurpleChauth sgc = (SilcPurpleChauth)user_data;
+	SilcPublicKey public_key;
+
 	silcpurple_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys);
-	silc_buffer_free(sgc->pubkeys);
+
+	if (sgc->pubkeys) {
+	  silc_dlist_start(sgc->pubkeys);
+	  while ((public_key = silc_dlist_get(sgc->pubkeys)))
+		silc_pkcs_public_key_free(public_key);
+	  silc_dlist_uninit(sgc->pubkeys);
+	}
 	silc_free(sgc);
 }
 
@@ -289,9 +302,9 @@
 	if (!purple_request_field_list_get_selected(f)) {
 		/* Add new public key */
 		purple_request_file(sg->gc, _("Open Public Key..."), NULL, FALSE,
-				  G_CALLBACK(silcpurple_chat_chpk_add),
-				  G_CALLBACK(silcpurple_chat_chpk_cancel),
-				  purple_connection_get_account(sg->gc), NULL, NULL, sgc);
+				    G_CALLBACK(silcpurple_chat_chpk_add),
+				    G_CALLBACK(silcpurple_chat_chpk_cancel),
+				    purple_connection_get_account(sg->gc), NULL, NULL, sgc);
 		return;
 	}
 
@@ -302,13 +315,12 @@
 		public_key = purple_request_field_list_get_data(f, list->data);
 		if (purple_request_field_list_is_selected(f, list->data)) {
 			/* Delete this public key */
-			pk = silc_pkcs_public_key_payload_encode(public_key);
+			pk = silc_public_key_payload_encode(public_key);
 			chpks = silc_argument_payload_encode_one(chpks, pk->data,
-								 pk->len, 0x01);
+								 silc_buffer_len(pk), 0x01);
 			silc_buffer_free(pk);
 			c++;
 		}
-		silc_pkcs_public_key_free(public_key);
 	}
 	if (!c) {
 		silc_buffer_free(chpks);
@@ -322,15 +334,20 @@
 
 	/* Send CMODE */
 	SILC_PUT32_MSB(m, mode);
-	chidp = silc_id_payload_encode(sgc->channel->id, SILC_ID_CHANNEL);
+	chidp = silc_id_payload_encode(&sgc->channel->id, SILC_ID_CHANNEL);
 	silc_client_command_send(client, conn, SILC_COMMAND_CMODE,
-				 ++conn->cmd_ident, 3,
-				 1, chidp->data, chidp->len,
+				 silcpurple_command_reply, NULL, 3,
+				 1, chidp->data, silc_buffer_len(chidp),
 				 2, mode, sizeof(mode),
-				 9, chpks->data, chpks->len);
+				 9, chpks->data, silc_buffer_len(chpks));
 	silc_buffer_free(chpks);
 	silc_buffer_free(chidp);
-	silc_buffer_free(sgc->pubkeys);
+	if (sgc->pubkeys) {
+	  silc_dlist_start(sgc->pubkeys);
+	  while ((public_key = silc_dlist_get(sgc->pubkeys)))
+		silc_pkcs_public_key_free(public_key);
+	  silc_dlist_uninit(sgc->pubkeys);
+	}
 	silc_free(sgc);
 }
 
@@ -339,6 +356,7 @@
 {
 	SilcPurple sg = sgc->sg;
 	PurpleRequestField *f;
+	SilcPublicKey public_key;
 	const char *curpass, *val;
 	int set;
 
@@ -365,19 +383,23 @@
 		purple_blist_node_remove_setting((PurpleBlistNode *)sgc->c, "passphrase");
 	}
 
-	silc_buffer_free(sgc->pubkeys);
+	if (sgc->pubkeys) {
+	  silc_dlist_start(sgc->pubkeys);
+	  while ((public_key = silc_dlist_get(sgc->pubkeys)))
+		silc_pkcs_public_key_free(public_key);
+	  silc_dlist_uninit(sgc->pubkeys);
+	}
 	silc_free(sgc);
 }
 
 void silcpurple_chat_chauth_show(SilcPurple sg, SilcChannelEntry channel,
-			       SilcBuffer channel_pubkeys)
+				 SilcDList channel_pubkeys)
 {
-	SilcUInt16 argc;
-	SilcArgumentPayload chpks;
+	SilcPublicKey public_key;
+	SilcSILCPublicKey silc_pubkey;
 	unsigned char *pk;
-	SilcUInt32 pk_len, type;
+	SilcUInt32 pk_len;
 	char *fingerprint, *babbleprint;
-	SilcPublicKey pubkey;
 	SilcPublicKeyIdentifier ident;
 	char tmp2[1024], t[512];
 	PurpleRequestFields *fields;
@@ -399,7 +421,7 @@
 
 	g = purple_request_field_group_new(NULL);
 	f = purple_request_field_string_new("passphrase", _("Channel Passphrase"),
-					  curpass, FALSE);
+					    curpass, FALSE);
 	purple_request_field_string_set_masked(f, TRUE);
 	purple_request_field_group_add_field(g, f);
 	purple_request_fields_add_group(fields, g);
@@ -416,55 +438,49 @@
 		     "is required to be able to join. If channel public keys are set "
 		     "then only users whose public keys are listed are able to join."));
 
-	if (!channel_pubkeys) {
+	if (!channel_pubkeys || !silc_dlist_count(channel_pubkeys)) {
 		f = purple_request_field_list_new("list", NULL);
 		purple_request_field_group_add_field(g, f);
 		purple_request_fields(sg->gc, _("Channel Authentication"),
-				    _("Channel Authentication"), t, fields,
-				    _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb),
-				    _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok),
-					purple_connection_get_account(sg->gc), NULL, NULL, sgc);
+				      _("Channel Authentication"), t, fields,
+				      _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb),
+				      _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok),
+				      purple_connection_get_account(sg->gc), NULL, NULL, sgc);
+		if (channel_pubkeys)
+		  silc_dlist_uninit(channel_pubkeys);
 		return;
 	}
-	sgc->pubkeys = silc_buffer_copy(channel_pubkeys);
+	sgc->pubkeys = channel_pubkeys;
 
 	g = purple_request_field_group_new(NULL);
 	f = purple_request_field_list_new("list", NULL);
 	purple_request_field_group_add_field(g, f);
 	purple_request_fields_add_group(fields, g);
 
-	SILC_GET16_MSB(argc, channel_pubkeys->data);
-	chpks = silc_argument_payload_parse(channel_pubkeys->data + 2,
-					    channel_pubkeys->len - 2, argc);
-	if (!chpks)
-		return;
-
-	pk = silc_argument_get_first_arg(chpks, &type, &pk_len);
-	while (pk) {
+	silc_dlist_start(channel_pubkeys);
+	while ((public_key = silc_dlist_get(channel_pubkeys))) {
+		pk = silc_pkcs_public_key_encode(public_key, &pk_len);
 		fingerprint = silc_hash_fingerprint(NULL, pk + 4, pk_len - 4);
 		babbleprint = silc_hash_babbleprint(NULL, pk + 4, pk_len - 4);
-		silc_pkcs_public_key_payload_decode(pk, pk_len, &pubkey);
-		ident = silc_pkcs_decode_identifier(pubkey->identifier);
+
+		silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key);
+		ident = &silc_pubkey->identifier;
 
 		g_snprintf(tmp2, sizeof(tmp2), "%s\n  %s\n  %s",
 			   ident->realname ? ident->realname : ident->username ?
 			   ident->username : "", fingerprint, babbleprint);
-		purple_request_field_list_add(f, tmp2, pubkey);
+		purple_request_field_list_add(f, tmp2, public_key);
 
 		silc_free(fingerprint);
 		silc_free(babbleprint);
-		silc_pkcs_free_identifier(ident);
-		pk = silc_argument_get_next_arg(chpks, &type, &pk_len);
 	}
 
 	purple_request_field_list_set_multi_select(f, FALSE);
 	purple_request_fields(sg->gc, _("Channel Authentication"),
-			    _("Channel Authentication"), t, fields,
-			    _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb),
-			    _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok),
-				purple_connection_get_account(sg->gc), NULL, NULL, sgc);
-
-	silc_argument_payload_free(chpks);
+			      _("Channel Authentication"), t, fields,
+			      _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb),
+			      _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok),
+			      purple_connection_get_account(sg->gc), NULL, NULL, sgc);
 }
 
 static void
@@ -525,9 +541,9 @@
 
 	/* Add private group to buddy list */
 	g_snprintf(tmp, sizeof(tmp), "%s [Private Group]", name);
-	comp = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-	g_hash_table_replace(comp, g_strdup("channel"), g_strdup(tmp));
-	g_hash_table_replace(comp, g_strdup("passphrase"), g_strdup(passphrase));
+	comp = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
+	g_hash_table_replace(comp, "channel", g_strdup(tmp));
+	g_hash_table_replace(comp, "passphrase", g_strdup(passphrase));
 
 	cn = purple_chat_new(sg->account, alias, comp);
 	g = (PurpleGroup *)p->c->node.parent;
@@ -596,9 +612,9 @@
 		   _("Please enter the %s channel private group name and passphrase."),
 		   p->channel);
 	purple_request_fields(gc, _("Add Channel Private Group"), NULL, tmp, fields,
-			    _("Add"), G_CALLBACK(silcpurple_chat_prv_add),
-			    _("Cancel"), G_CALLBACK(silcpurple_chat_prv_cancel),
-				purple_connection_get_account(gc), NULL, NULL, p);
+			      _("Add"), G_CALLBACK(silcpurple_chat_prv_add),
+			      _("Cancel"), G_CALLBACK(silcpurple_chat_prv_cancel),
+			      purple_connection_get_account(gc), NULL, NULL, p);
 }
 
 
@@ -907,7 +923,7 @@
 		m = g_list_append(m, act);
 	}
 
-	if (mode & SILC_CHANNEL_UMODE_CHANFO) {
+	if (chu && mode & SILC_CHANNEL_UMODE_CHANFO) {
 		act = purple_menu_action_new(_("Channel Authentication"),
 		                           PURPLE_CALLBACK(silcpurple_chat_chauth),
 		                           NULL, NULL);
@@ -926,7 +942,7 @@
 		}
 	}
 
-	if (mode & SILC_CHANNEL_UMODE_CHANOP) {
+	if (chu && mode & SILC_CHANNEL_UMODE_CHANOP) {
 		act = purple_menu_action_new(_("Set User Limit"),
 		                           PURPLE_CALLBACK(silcpurple_chat_ulimit),
 		                           NULL, NULL);
@@ -969,7 +985,7 @@
 		}
 	}
 
-	if (channel) {
+	if (chu && channel) {
 		SilcPurpleChatWb wb;
 		wb = silc_calloc(1, sizeof(*wb));
 		wb->sg = sg;
@@ -986,86 +1002,10 @@
 
 /******************************* Joining Etc. ********************************/
 
-void silcpurple_chat_join_done(SilcClient client,
-			     SilcClientConnection conn,
-			     SilcClientEntry *clients,
-			     SilcUInt32 clients_count,
-			     void *context)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
-	SilcChannelEntry channel = context;
-	PurpleConversation *convo;
-	SilcUInt32 retry = SILC_PTR_TO_32(channel->context);
-	SilcHashTableList htl;
-	SilcChannelUser chu;
-	GList *users = NULL, *flags = NULL;
-	char tmp[256];
-
-	if (!clients && retry < 1) {
-		/* Resolving users failed, try again. */
-		channel->context = SILC_32_TO_PTR(retry + 1);
-		silc_client_get_clients_by_channel(client, conn, channel,
-						   silcpurple_chat_join_done, channel);
-		return;
-	}
-
-	/* Add channel to Purple */
-	channel->context = SILC_32_TO_PTR(++sg->channel_ids);
-	serv_got_joined_chat(gc, sg->channel_ids, channel->channel_name);
-	convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-							channel->channel_name, sg->account);
-	if (!convo)
-		return;
-
-	/* Add all users to channel */
-	silc_hash_table_list(channel->user_list, &htl);
-	while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-		PurpleConvChatBuddyFlags f = PURPLE_CBFLAGS_NONE;
-		if (!chu->client->nickname)
-			continue;
-		chu->context = SILC_32_TO_PTR(sg->channel_ids);
-
-		if (chu->mode & SILC_CHANNEL_UMODE_CHANFO)
-			f |= PURPLE_CBFLAGS_FOUNDER;
-		if (chu->mode & SILC_CHANNEL_UMODE_CHANOP)
-			f |= PURPLE_CBFLAGS_OP;
-		users = g_list_append(users, g_strdup(chu->client->nickname));
-		flags = g_list_append(flags, GINT_TO_POINTER(f));
-
-		if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) {
-			if (chu->client == conn->local_entry)
-				g_snprintf(tmp, sizeof(tmp),
-					   _("You are channel founder on <I>%s</I>"),
-					   channel->channel_name);
-			else
-				g_snprintf(tmp, sizeof(tmp),
-					   _("Channel founder on <I>%s</I> is <I>%s</I>"),
-					   channel->channel_name, chu->client->nickname);
-
-			purple_conversation_write(convo, NULL, tmp,
-						PURPLE_MESSAGE_SYSTEM, time(NULL));
-
-		}
-	}
-	silc_hash_table_list_reset(&htl);
-
-	purple_conv_chat_add_users(PURPLE_CONV_CHAT(convo), users, NULL, flags, FALSE);
-	g_list_free(users);
-	g_list_free(flags);
-
-	/* Set topic */
-	if (channel->topic)
-		purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, channel->topic);
-
-	/* Set nick */
-	purple_conv_chat_set_nick(PURPLE_CONV_CHAT(convo), conn->local_entry->nickname);
-}
-
 char *silcpurple_get_chat_name(GHashTable *data)
 {
 	return g_strdup(g_hash_table_lookup(data, "channel"));
-}	
+}
 
 void silcpurple_chat_join(PurpleConnection *gc, GHashTable *data)
 {
@@ -1073,6 +1013,9 @@
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
 	const char *channel, *passphrase, *parentch;
+#if 0
+	PurpleChat *chat;
+#endif
 
 	if (!conn)
 		return;
@@ -1128,6 +1071,22 @@
 		return;
 	}
 
+#if 0
+	/* If the channel is not on buddy list, automatically add it there. */
+	chat = purple_blist_find_chat(sg->account, channel);
+	if (!chat) {
+		data = g_hash_table_new_full(g_str_hash, g_str_equal,
+					     g_free, g_free);
+		g_hash_table_replace(data, g_strdup("channel"),
+				     g_strdup(channel));
+		if (passphrase)
+		  g_hash_table_replace(data, g_strdup("passphrase"),
+				       g_strdup(passphrase));
+		chat = purple_chat_new(sg->account, NULL, data);
+		purple_blist_add_chat(chat, NULL, NULL);
+	}
+#endif
+
 	/* XXX We should have other properties here as well:
 	   1. whether to try to authenticate to the channel
 	     1a. with default key,
@@ -1150,7 +1109,7 @@
 }
 
 void silcpurple_chat_invite(PurpleConnection *gc, int id, const char *msg,
-			  const char *name)
+			    const char *name)
 {
 	SilcPurple sg = gc->proto_data;
 	SilcClient client = sg->client;
@@ -1264,7 +1223,8 @@
 		}
 }
 
-int silcpurple_chat_send(PurpleConnection *gc, int id, const char *msg, PurpleMessageFlags msgflags)
+int silcpurple_chat_send(PurpleConnection *gc, int id, const char *msg,
+			 PurpleMessageFlags msgflags)
 {
 	SilcPurple sg = gc->proto_data;
 	SilcClient client = sg->client;
@@ -1274,10 +1234,11 @@
 	SilcChannelEntry channel = NULL;
 	SilcChannelPrivateKey key = NULL;
 	SilcUInt32 flags;
-	int ret;
+	int ret = 0;
 	char *msg2, *tmp;
 	gboolean found = FALSE;
 	gboolean sign = purple_account_get_bool(sg->account, "sign-verify", FALSE);
+	SilcDList list;
 
 	if (!msg || !conn)
 		return 0;
@@ -1297,7 +1258,7 @@
 	} else if (strlen(msg) > 1 && msg[0] == '/') {
 		if (!silc_client_command_call(client, conn, msg + 1))
 			purple_notify_error(gc, _("Call Command"), _("Cannot call command"),
-							  _("Unknown command"));
+					    _("Unknown command"));
 		g_free(tmp);
 		return 0;
 	}
@@ -1346,10 +1307,35 @@
 		channel = chu->channel;
 	}
 
+	/* Check for images */
+	if (msgflags & PURPLE_MESSAGE_IMAGES) {
+		list = silcpurple_image_message(msg, &flags);
+		if (list) {
+			/* Send one or more MIME message.  If more than one, they
+			   are MIME fragments due to over large message */
+			SilcBuffer buf;
+
+			silc_dlist_start(list);
+			while ((buf = silc_dlist_get(list)) != SILC_LIST_END)
+				ret =
+			 	silc_client_send_channel_message(client, conn,
+								 channel, key,
+								 flags, NULL,
+								 buf->data,
+								 silc_buffer_len(buf));
+			silc_mime_partial_free(list);
+			g_free(tmp);
+
+			if (ret)
+				  serv_got_chat_in(gc, id, purple_connection_get_display_name(gc), 0, msg, time(NULL));
+			return ret;
+		}
+	}
+
 	/* Send channel message */
 	ret = silc_client_send_channel_message(client, conn, channel, key,
-					       flags, (unsigned char *)msg2,
-					       strlen(msg2), TRUE);
+					       flags, NULL, (unsigned char *)msg2,
+					       strlen(msg2));
 	if (ret) {
 		serv_got_chat_in(gc, id, purple_connection_get_display_name(gc), 0, msg,
 				 time(NULL));
--- a/libpurple/protocols/silc/ft.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/silc/ft.c	Mon Jun 18 01:48:35 2007 +0000
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2004 Pekka Riikonen
+  Copyright (C) 2004 - 2007 Pekka Riikonen
 
   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
@@ -17,7 +17,7 @@
 
 */
 
-#include "silcincludes.h"
+#include "silc.h"
 #include "silcclient.h"
 #include "silcpurple.h"
 
@@ -74,11 +74,23 @@
 	char tmp[256];
 
 	if (status == SILC_CLIENT_FILE_MONITOR_CLOSED) {
+		/* All started sessions terminate here */
+		xfer->xfer->data = NULL;
 		purple_xfer_unref(xfer->xfer);
 		silc_free(xfer);
 		return;
 	}
 
+	if (status == SILC_CLIENT_FILE_MONITOR_DISCONNECT) {
+		purple_notify_error(gc, _("Secure File Transfer"),
+				    _("Error during file transfer"),
+				    _("Remote disconnected"));
+		xfer->xfer->status = PURPLE_XFER_STATUS_CANCEL_REMOTE;
+		purple_xfer_update_progress(xfer->xfer);
+		silc_client_file_close(client, conn, session_id);
+		return;
+	}
+
 	if (status == SILC_CLIENT_FILE_MONITOR_KEY_AGREEMENT)
 		return;
 
@@ -96,17 +108,22 @@
 			purple_notify_error(gc, _("Secure File Transfer"),
 					  _("Error during file transfer"),
 					  _("Key agreement failed"));
+		} else if (error == SILC_CLIENT_FILE_TIMEOUT) {
+			purple_notify_error(gc, _("Secure File Transfer"),
+					  _("Error during file transfer"),
+					  _("Connection timedout"));
+		} else if (error == SILC_CLIENT_FILE_CONNECT_FAILED) {
+			purple_notify_error(gc, _("Secure File Transfer"),
+					  _("Error during file transfer"),
+					  _("Creating connection failed"));
 		} else if (error == SILC_CLIENT_FILE_UNKNOWN_SESSION) {
 			purple_notify_error(gc, _("Secure File Transfer"),
 					  _("Error during file transfer"),
 					  _("File transfer session does not exist"));
-		} else {
-			purple_notify_error(gc, _("Secure File Transfer"),
-					  _("Error during file transfer"), NULL);
 		}
+		xfer->xfer->status = PURPLE_XFER_STATUS_CANCEL_REMOTE;
+		purple_xfer_update_progress(xfer->xfer);
 		silc_client_file_close(client, conn, session_id);
-		purple_xfer_unref(xfer->xfer);
-		silc_free(xfer);
 		return;
 	}
 
@@ -133,6 +150,10 @@
 silcpurple_ftp_cancel(PurpleXfer *x)
 {
 	SilcPurpleXfer xfer = x->data;
+
+	if (!xfer)
+		return;
+
 	xfer->xfer->status = PURPLE_XFER_STATUS_CANCEL_LOCAL;
 	purple_xfer_update_progress(xfer->xfer);
 	silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id);
@@ -143,6 +164,9 @@
 {
 	SilcPurpleXfer xfer = x->data;
 
+	if (!xfer)
+		return;
+
 	/* Cancel the transmission */
 	xfer->completion(NULL, xfer->completion_context);
 	silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id);
@@ -154,6 +178,9 @@
 	SilcPurpleXfer xfer = x->data;
 	const char *name;
 
+	if (!xfer)
+		return;
+
 	name = purple_xfer_get_local_filename(x);
 	g_unlink(name);
 	xfer->completion(name, xfer->completion_context);
@@ -187,17 +214,57 @@
 	SilcPurpleXfer xfer = x->data;
 	SilcClientFileError status;
 	PurpleConnection *gc = xfer->sg->gc;
+	SilcClientConnectionParams params;
+	gboolean local = xfer->hostname ? FALSE : TRUE;
+	char *local_ip = NULL, *remote_ip = NULL;
+	SilcSocket sock;
 
 	if (purple_xfer_get_status(x) != PURPLE_XFER_STATUS_ACCEPTED)
 		return;
+	if (!xfer)
+		return;
+
+	silc_socket_stream_get_info(silc_packet_stream_get_stream(xfer->sg->conn->stream),
+				    &sock, NULL, NULL, NULL);
+
+	if (local) {
+		/* Do the same magic what we do with key agreement (see silcpurple_buddy.c)
+		   to see if we are behind NAT. */
+		if (silc_net_check_local_by_sock(sock, NULL, &local_ip)) {
+			/* Check if the IP is private */
+			if (silcpurple_ip_is_private(local_ip)) {
+				local = TRUE;
+				/* Local IP is private, resolve the remote server IP to see whether
+				   we are talking to Internet or just on LAN. */
+				if (silc_net_check_host_by_sock(sock, NULL,
+								&remote_ip))
+				  if (silcpurple_ip_is_private(remote_ip))
+				    /* We assume we are in LAN.  Let's provide the connection point. */
+				    local = TRUE;
+			}
+		}
+
+		if (local && !local_ip)
+		  local_ip = silc_net_localip();
+	}
+
+	memset(&params, 0, sizeof(params));
+	params.timeout_secs = 60;
+	if (local)
+	  /* Provide connection point */
+	  params.local_ip = local_ip;
 
 	/* Start the file transfer */
 	status = silc_client_file_receive(xfer->sg->client, xfer->sg->conn,
+					  &params, xfer->sg->public_key,
+					  xfer->sg->private_key,
 					  silcpurple_ftp_monitor, xfer,
 					  NULL, xfer->session_id,
 					  silcpurple_ftp_ask_name, xfer);
 	switch (status) {
 	case SILC_CLIENT_FILE_OK:
+		silc_free(local_ip);
+		silc_free(remote_ip);
 		return;
 		break;
 
@@ -227,6 +294,8 @@
 	purple_xfer_unref(xfer->xfer);
 	g_free(xfer->hostname);
 	silc_free(xfer);
+	silc_free(local_ip);
+	silc_free(remote_ip);
 }
 
 static void
@@ -236,8 +305,8 @@
 }
 
 void silcpurple_ftp_request(SilcClient client, SilcClientConnection conn,
-			  SilcClientEntry client_entry, SilcUInt32 session_id,
-			  const char *hostname, SilcUInt16 port)
+			    SilcClientEntry client_entry, SilcUInt32 session_id,
+			    const char *hostname, SilcUInt16 port)
 {
 	PurpleConnection *gc = client->application;
 	SilcPurple sg = gc->proto_data;
@@ -255,7 +324,7 @@
 	xfer->hostname = g_strdup(hostname);
 	xfer->port = port;
 	xfer->xfer = purple_xfer_new(xfer->sg->account, PURPLE_XFER_RECEIVE,
-				   xfer->client_entry->nickname);
+				     xfer->client_entry->nickname);
 	if (!xfer->xfer) {
 		silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id);
 		g_free(xfer->hostname);
@@ -277,10 +346,12 @@
 silcpurple_ftp_send_cancel(PurpleXfer *x)
 {
 	SilcPurpleXfer xfer = x->data;
+
+	if (!xfer)
+		return;
+
+	/* This call will free all resources */
 	silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id);
-	purple_xfer_unref(xfer->xfer);
-	g_free(xfer->hostname);
-	silc_free(xfer);
 }
 
 static void
@@ -290,19 +361,26 @@
 	const char *name;
 	char *local_ip = NULL, *remote_ip = NULL;
 	gboolean local = TRUE;
+	SilcClientConnectionParams params;
+	SilcSocket sock;
+
+	if (!xfer)
+		return;
 
 	name = purple_xfer_get_local_filename(x);
 
+	silc_socket_stream_get_info(silc_packet_stream_get_stream(xfer->sg->conn->stream),
+				    &sock, NULL, NULL, NULL);
+
 	/* Do the same magic what we do with key agreement (see silcpurple_buddy.c)
 	   to see if we are behind NAT. */
-	if (silc_net_check_local_by_sock(xfer->sg->conn->sock->sock,
-					 NULL, &local_ip)) {
+	if (silc_net_check_local_by_sock(sock, NULL, &local_ip)) {
 		/* Check if the IP is private */
 		if (silcpurple_ip_is_private(local_ip)) {
 			local = FALSE;
 			/* Local IP is private, resolve the remote server IP to see whether
 			   we are talking to Internet or just on LAN. */
-			if (silc_net_check_host_by_sock(xfer->sg->conn->sock->sock, NULL,
+			if (silc_net_check_host_by_sock(sock, NULL,
 							&remote_ip))
 				if (silcpurple_ip_is_private(remote_ip))
 					/* We assume we are in LAN.  Let's provide the connection point. */
@@ -313,10 +391,17 @@
 	if (local && !local_ip)
 		local_ip = silc_net_localip();
 
+	memset(&params, 0, sizeof(params));
+	params.timeout_secs = 60;
+	if (local)
+	  /* Provide connection point */
+	  params.local_ip = local_ip;
+
 	/* Send the file */
 	silc_client_file_send(xfer->sg->client, xfer->sg->conn,
+			      xfer->client_entry, &params,
+			      xfer->sg->public_key, xfer->sg->private_key,
 			      silcpurple_ftp_monitor, xfer,
-			      local_ip, 0, !local, xfer->client_entry,
 			      name, &xfer->session_id);
 
 	silc_free(local_ip);
@@ -325,10 +410,10 @@
 
 static void
 silcpurple_ftp_send_file_resolved(SilcClient client,
-				SilcClientConnection conn,
-				SilcClientEntry *clients,
-				SilcUInt32 clients_count,
-				void *context)
+				  SilcClientConnection conn,
+				  SilcStatus status,
+				  SilcDList clients,
+				  void *context)
 {
 	PurpleConnection *gc = client->application;
 	char tmp[256];
@@ -352,38 +437,29 @@
 	SilcPurple sg = gc->proto_data;
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
-	SilcClientEntry *clients;
-	SilcUInt32 clients_count;
+	SilcDList clients;
 	SilcPurpleXfer xfer;
-	char *nickname;
 
 	g_return_val_if_fail(name != NULL, NULL);
 
-	if (!silc_parse_userfqdn(name, &nickname, NULL))
-		return NULL;
-
 	/* Find client entry */
-	clients = silc_client_get_clients_local(client, conn, nickname, name,
-											&clients_count);
+	clients = silc_client_get_clients_local(client, conn, name, FALSE);
 	if (!clients) {
-		silc_client_get_clients(client, conn, nickname, NULL,
-								silcpurple_ftp_send_file_resolved,
-								strdup(name));
-		silc_free(nickname);
+		silc_client_get_clients(client, conn, name, NULL,
+					silcpurple_ftp_send_file_resolved,
+					strdup(name));
 		return NULL;
 	}
+	silc_dlist_start(clients);
 
 	xfer = silc_calloc(1, sizeof(*xfer));
-
 	g_return_val_if_fail(xfer != NULL, NULL);
 
 	xfer->sg = sg;
-	xfer->client_entry = clients[0];
+	xfer->client_entry = silc_dlist_get(clients);
 	xfer->xfer = purple_xfer_new(xfer->sg->account, PURPLE_XFER_SEND,
-							   xfer->client_entry->nickname);
+				     xfer->client_entry->nickname);
 	if (!xfer->xfer) {
-		silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id);
-		g_free(xfer->hostname);
 		silc_free(xfer);
 		return NULL;
 	}
@@ -393,7 +469,6 @@
 	xfer->xfer->data = xfer;
 
 	silc_free(clients);
-	silc_free(nickname);
 
 	return xfer->xfer;
 }
--- a/libpurple/protocols/silc/ops.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/silc/ops.c	Mon Jun 18 01:48:35 2007 +0000
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2004 Pekka Riikonen
+  Copyright (C) 2004 - 2007 Pekka Riikonen
 
   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
@@ -17,7 +17,7 @@
 
 */
 
-#include "silcincludes.h"
+#include "silc.h"
 #include "silcclient.h"
 #include "silcpurple.h"
 #include "imgstore.h"
@@ -26,14 +26,18 @@
 static void
 silc_channel_message(SilcClient client, SilcClientConnection conn,
 		     SilcClientEntry sender, SilcChannelEntry channel,
-		     SilcMessagePayload payload, SilcChannelPrivateKey key,
-		     SilcMessageFlags flags, const unsigned char *message,
+		     SilcMessagePayload payload,
+		     SilcChannelPrivateKey key, SilcMessageFlags flags,
+		     const unsigned char *message,
 		     SilcUInt32 message_len);
 static void
 silc_private_message(SilcClient client, SilcClientConnection conn,
 		     SilcClientEntry sender, SilcMessagePayload payload,
 		     SilcMessageFlags flags, const unsigned char *message,
 		     SilcUInt32 message_len);
+static void
+silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
+		    SilcAskPassphrase completion, void *context);
 
 /* Message sent to the application by library. `conn' associates the
    message to a specific connection.  `conn', however, may be NULL.
@@ -41,23 +45,31 @@
    The application can for example filter the message according the
    type. */
 
-static void
-silc_say(SilcClient client, SilcClientConnection conn,
-	 SilcClientMessageType type, char *msg, ...)
+void silc_say(SilcClient client, SilcClientConnection conn,
+	      SilcClientMessageType type, char *msg, ...)
 {
-	/* Nothing */
+	if (type == SILC_CLIENT_MESSAGE_ERROR) {
+		char tmp[256];
+		va_list va;
+
+		va_start(va, msg);
+		silc_vsnprintf(tmp, sizeof(tmp), msg, va);
+		purple_notify_error(NULL, _("Error"), _("Error occurred"), tmp);
+
+		va_end(va);
+		return;
+	}
 }
 
-#ifdef HAVE_SILCMIME_H
 /* Processes incoming MIME message.  Can be private message or channel
-   message. */
+   message.  Returns TRUE if the message `mime' was displayed. */
 
-static void
+static SilcBool
 silcpurple_mime_message(SilcClient client, SilcClientConnection conn,
-		      SilcClientEntry sender, SilcChannelEntry channel,
-		      SilcMessagePayload payload, SilcChannelPrivateKey key,
-		      SilcMessageFlags flags, SilcMime mime,
-		      gboolean recursive)
+			SilcClientEntry sender, SilcChannelEntry channel,
+			SilcMessagePayload payload, SilcChannelPrivateKey key,
+			SilcMessageFlags flags, SilcMime mime,
+			gboolean recursive)
 {
 	PurpleConnection *gc = client->application;
 	SilcPurple sg = gc->proto_data;
@@ -66,9 +78,10 @@
 	SilcUInt32 data_len;
 	PurpleMessageFlags cflags = 0;
 	PurpleConversation *convo = NULL;
+	SilcBool ret = FALSE;
 
 	if (!mime)
-		return;
+		return FALSE;
 
 	/* Check for fragmented MIME message */
 	if (silc_mime_is_partial(mime)) {
@@ -79,12 +92,12 @@
 		mime = silc_mime_assemble(sg->mimeass, mime);
 		if (!mime)
 			/* More fragments to come */
-			return;
+			return FALSE;
 
 		/* Process the complete message */
-		silcpurple_mime_message(client, conn, sender, channel,
-				      payload, key, flags, mime, FALSE);
-		return;
+		return silcpurple_mime_message(client, conn, sender, channel,
+					       payload, key, flags, mime,
+					       FALSE);
 	}
 
 	/* Check for multipart message */
@@ -92,17 +105,33 @@
 		SilcMime p;
 		const char *mtype;
 		SilcDList parts = silc_mime_get_multiparts(mime, &mtype);
+		SilcBool ret;
 
-		/* Only "mixed" type supported */
-		if (strcmp(mtype, "mixed"))
-			goto out;
+		if (!strcmp(mtype, "mixed")) {
+			/* Contains multiple messages */
+			silc_dlist_start(parts);
+			while ((p = silc_dlist_get(parts)) != SILC_LIST_END) {
+			  /* Recursively process parts */
+			  ret = silcpurple_mime_message(client, conn, sender, channel,
+							payload, key, flags, p, TRUE);
+			}
+		}
 
-		silc_dlist_start(parts);
-		while ((p = silc_dlist_get(parts)) != SILC_LIST_END) {
-			/* Recursively process parts */
-			silcpurple_mime_message(client, conn, sender, channel,
-					      payload, key, flags, p, TRUE);
+		if (!strcmp(mtype, "alternative")) {
+			/* Same message in alternative formats.  Kopete sends
+			   these.  Go in order from last to first. */
+			silc_dlist_end(parts);
+			while ((p = silc_dlist_get(parts)) != SILC_LIST_END) {
+			  /* Go through the alternatives and display the first
+			     one we support. */
+			  if (silcpurple_mime_message(client, conn, sender, channel,
+						      payload, key, flags, p, TRUE)) {
+			    ret = TRUE;
+			    break;
+			  }
+			}
 		}
+
 		goto out;
 	}
 
@@ -124,13 +153,14 @@
 
 		if (channel)
 			silc_channel_message(client, conn, sender, channel,
-					     payload, key, 
+					     payload, key,
 					     SILC_MESSAGE_FLAG_UTF8, data,
 					     data_len);
 		else
 			silc_private_message(client, conn, sender, payload,
 					     SILC_MESSAGE_FLAG_UTF8, data,
 					     data_len);
+		ret = TRUE;
 		goto out;
 	}
 
@@ -157,7 +187,7 @@
 		}
 		if (channel && !convo)
 			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-								    channel->channel_name, sg->account);
+								      channel->channel_name, sg->account);
 		if (channel && !convo)
 			goto out;
 
@@ -165,11 +195,11 @@
 		if (imgid) {
 			cflags |= PURPLE_MESSAGE_IMAGES | PURPLE_MESSAGE_RECV;
 			g_snprintf(tmp, sizeof(tmp), "<IMG ID=\"%d\">", imgid);
-		  
+
 			if (channel)
 				serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)),
 				 		 sender->nickname ?
-				 		  sender->nickname : 
+				 		  sender->nickname :
 						 "<unknown>", cflags,
 						 tmp, time(NULL));
 			else
@@ -179,6 +209,7 @@
 
 			purple_imgstore_unref_by_id(imgid);
 			cflags = 0;
+			ret = TRUE;
 		}
 		goto out;
 	}
@@ -191,15 +222,16 @@
 					       payload, flags, data, data_len);
 		else
 			silcpurple_wb_receive(client, conn, sender, payload,
-					    flags, data, data_len);
+					      flags, data, data_len);
+		ret = TRUE;
 		goto out;
 	}
 
  out:
 	if (!recursive)
 		silc_mime_free(mime);
+	return ret;
 }
-#endif /* HAVE_SILCMIME_H */
 
 /* Message for a channel. The `sender' is the sender of the message
    The `channel' is the channel. The `message' is the message.  Note
@@ -210,8 +242,9 @@
 static void
 silc_channel_message(SilcClient client, SilcClientConnection conn,
 		     SilcClientEntry sender, SilcChannelEntry channel,
-		     SilcMessagePayload payload, SilcChannelPrivateKey key,
-		     SilcMessageFlags flags, const unsigned char *message,
+		     SilcMessagePayload payload,
+		     SilcChannelPrivateKey key, SilcMessageFlags flags,
+		     const unsigned char *message,
 		     SilcUInt32 message_len)
 {
 	PurpleConnection *gc = client->application;
@@ -236,7 +269,7 @@
 	}
 	if (!convo)
 		convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-								channel->channel_name, sg->account);
+							      channel->channel_name, sg->account);
 	if (!convo)
 		return;
 
@@ -247,30 +280,10 @@
 
 	if (flags & SILC_MESSAGE_FLAG_DATA) {
 		/* Process MIME message */
-#ifdef HAVE_SILCMIME_H
 		SilcMime mime;
-		mime = silc_mime_decode(message, message_len);
+		mime = silc_mime_decode(NULL, message, message_len);
 		silcpurple_mime_message(client, conn, sender, channel, payload,
-				      key, flags, mime, FALSE);
-#else
-		char type[128], enc[128];
-		unsigned char *data;
-		SilcUInt32 data_len;
-
-		memset(type, 0, sizeof(type));
-		memset(enc, 0, sizeof(enc));
-
-		if (!silc_mime_parse(message, message_len, NULL, 0,
-		    type, sizeof(type) - 1, enc, sizeof(enc) - 1, &data,
-		    &data_len))
-			return;
-
-		if (!strcmp(type, "application/x-wb") &&
-		    !strcmp(enc, "binary") &&
-		    !purple_account_get_bool(sg->account, "block-wb", FALSE))
-			silcpurple_wb_receive_ch(client, conn, sender, channel,
-					       payload, flags, data, data_len);
-#endif
+					key, flags, mime, FALSE);
 		return;
 	}
 
@@ -283,9 +296,7 @@
 		tmp = g_markup_escape_text(msg, -1);
 		/* Send to Purple */
 		serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)),
-				 sender->nickname ?
-				 sender->nickname : "<unknown>", 0,
-				 tmp, time(NULL));
+				 sender->nickname, 0, tmp, time(NULL));
 		g_free(tmp);
 		g_free(msg);
 		return;
@@ -293,9 +304,7 @@
 
 	if (flags & SILC_MESSAGE_FLAG_NOTICE) {
 		msg = g_strdup_printf("(notice) <I>%s</I> %s",
-				      sender->nickname ?
-				      sender->nickname : "<unknown>",
-				      (const char *)message);
+				      sender->nickname, (const char *)message);
 		if (!msg)
 			return;
 
@@ -310,9 +319,7 @@
 		tmp = g_markup_escape_text((const char *)message, -1);
 		/* Send to Purple */
 		serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)),
-				 sender->nickname ?
-				 sender->nickname : "<unknown>", 0,
-				 tmp, time(NULL));
+				 sender->nickname, 0, tmp, time(NULL));
 		g_free(tmp);
 	}
 }
@@ -341,7 +348,7 @@
 	if (sender->nickname)
 		/* XXX - Should this be PURPLE_CONV_TYPE_IM? */
 		convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY,
-								sender->nickname, sg->account);
+							      sender->nickname, sg->account);
 
 	if (flags & SILC_MESSAGE_FLAG_SIGNED &&
 	    purple_account_get_bool(sg->account, "sign-verify", FALSE)) {
@@ -349,31 +356,11 @@
 	}
 
 	if (flags & SILC_MESSAGE_FLAG_DATA) {
-#ifdef HAVE_SILCMIME_H
 		/* Process MIME message */
 		SilcMime mime;
-		mime = silc_mime_decode(message, message_len);
+		mime = silc_mime_decode(NULL, message, message_len);
 		silcpurple_mime_message(client, conn, sender, NULL, payload,
 				      NULL, flags, mime, FALSE);
-#else
-		char type[128], enc[128];
-		unsigned char *data;
-		SilcUInt32 data_len;
-
-		memset(type, 0, sizeof(type));
-		memset(enc, 0, sizeof(enc));
-
-		if (!silc_mime_parse(message, message_len, NULL, 0,
-		    type, sizeof(type) - 1, enc, sizeof(enc) - 1, &data, 
-		    &data_len))
-			return;
-
-		if (!strcmp(type, "application/x-wb") &&
-		    !strcmp(enc, "binary") &&
-		    !purple_account_get_bool(sg->account, "block-wb", FALSE))
-			silcpurple_wb_receive(client, conn, sender, payload,
-					    flags, data, data_len);
-#endif
 		return;
 	}
 
@@ -383,11 +370,9 @@
 		if (!msg)
 			return;
 
+		/* Send to Purple */
 		tmp = g_markup_escape_text(msg, -1);
-		/* Send to Purple */
-		serv_got_im(gc, sender->nickname ?
-			    sender->nickname : "<unknown>",
-			    tmp, 0, time(NULL));
+		serv_got_im(gc, sender->nickname, tmp, 0, time(NULL));
 		g_free(msg);
 		g_free(tmp);
 		return;
@@ -395,15 +380,13 @@
 
 	if (flags & SILC_MESSAGE_FLAG_NOTICE && convo) {
 		msg = g_strdup_printf("(notice) <I>%s</I> %s",
-				      sender->nickname ?
-				      sender->nickname : "<unknown>",
-				      (const char *)message);
+				      sender->nickname, (const char *)message);
 		if (!msg)
 			return;
 
 		/* Send to Purple */
 		purple_conversation_write(convo, NULL, (const char *)msg,
-					PURPLE_MESSAGE_SYSTEM, time(NULL));
+					  PURPLE_MESSAGE_SYSTEM, time(NULL));
 		g_free(msg);
 		return;
 	}
@@ -411,9 +394,7 @@
 	if (flags & SILC_MESSAGE_FLAG_UTF8) {
 		tmp = g_markup_escape_text((const char *)message, -1);
 		/* Send to Purple */
-		serv_got_im(gc, sender->nickname ?
-			    sender->nickname : "<unknown>",
-			    tmp, 0, time(NULL));
+		serv_got_im(gc, sender->nickname, tmp, 0, time(NULL));
 		g_free(tmp);
 	}
 }
@@ -447,6 +428,7 @@
 	char buf[512], buf2[512], *tmp, *name;
 	SilcNotifyType notify;
 	PurpleBuddy *b;
+	SilcDList list;
 	int i;
 
 	va_start(va, type);
@@ -460,7 +442,7 @@
 	case SILC_NOTIFY_TYPE_INVITE:
 		{
 			GHashTable *components;
-			va_arg(va, SilcChannelEntry);
+			(void)va_arg(va, SilcChannelEntry);
 			name = va_arg(va, char *);
 			client_entry = va_arg(va, SilcClientEntry);
 
@@ -479,7 +461,7 @@
 			break;
 
 		convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-								channel->channel_name, sg->account);
+							      channel->channel_name, sg->account);
 		if (!convo)
 			break;
 
@@ -487,7 +469,7 @@
 		g_snprintf(buf, sizeof(buf), "%s@%s",
 			   client_entry->username, client_entry->hostname);
 		purple_conv_chat_add_user(PURPLE_CONV_CHAT(convo),
-					g_strdup(client_entry->nickname), buf, PURPLE_CBFLAGS_NONE, TRUE);
+					  g_strdup(client_entry->nickname), buf, PURPLE_CBFLAGS_NONE, TRUE);
 
 		break;
 
@@ -496,13 +478,13 @@
 		channel = va_arg(va, SilcChannelEntry);
 
 		convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-								channel->channel_name, sg->account);
+							      channel->channel_name, sg->account);
 		if (!convo)
 			break;
 
 		/* Remove user from channel */
 		purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo),
-					   client_entry->nickname, NULL);
+					     client_entry->nickname, NULL);
 
 		break;
 
@@ -510,19 +492,16 @@
 		client_entry = va_arg(va, SilcClientEntry);
 		tmp = va_arg(va, char *);
 
-		if (!client_entry->nickname)
-			break;
-
 		/* Remove from all channels */
 		silc_hash_table_list(client_entry->channels, &htl);
 		while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
 			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-									chu->channel->channel_name, sg->account);
+								      chu->channel->channel_name, sg->account);
 			if (!convo)
 				continue;
 			purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo),
-						   client_entry->nickname,
-						   tmp);
+						     client_entry->nickname,
+						     tmp);
 		}
 		silc_hash_table_list_reset(&htl);
 
@@ -537,7 +516,7 @@
 			channel = va_arg(va, SilcChannelEntry);
 
 			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-									channel->channel_name, sg->account);
+								      channel->channel_name, sg->account);
 			if (!convo)
 				break;
 
@@ -586,22 +565,22 @@
 		}
 	case SILC_NOTIFY_TYPE_NICK_CHANGE:
 		client_entry = va_arg(va, SilcClientEntry);
-		client_entry2 = va_arg(va, SilcClientEntry);
+		tmp = va_arg(va, char *);      /* Old nick */
+		name = va_arg(va, char *);     /* New nick */
 
-		if (!strcmp(client_entry->nickname, client_entry2->nickname))
+		if (!strcmp(tmp, name))
 			break;
 
 		/* Change nick on all channels */
-		silc_hash_table_list(client_entry2->channels, &htl);
+		silc_hash_table_list(client_entry->channels, &htl);
 		while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
 			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-									chu->channel->channel_name, sg->account);
+								      chu->channel->channel_name, sg->account);
 			if (!convo)
 				continue;
 			if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(convo), client_entry->nickname))
 				purple_conv_chat_rename_user(PURPLE_CONV_CHAT(convo),
-										   client_entry->nickname,
-										   client_entry2->nickname);
+							     tmp, name);
 		}
 		silc_hash_table_list_reset(&htl);
 
@@ -615,11 +594,11 @@
 		(void)va_arg(va, char *);
 		(void)va_arg(va, char *);
 		(void)va_arg(va, SilcPublicKey);
-		(void)va_arg(va, SilcBuffer);
+		(void)va_arg(va, SilcDList);
 		channel = va_arg(va, SilcChannelEntry);
 
 		convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-								channel->channel_name, sg->account);
+							      channel->channel_name, sg->account);
 		if (!convo)
 			break;
 
@@ -643,7 +622,7 @@
 				   channel->channel_name);
 		}
 		purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name,
-				     buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
+				       buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
 		break;
 
 	case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
@@ -656,7 +635,7 @@
 			channel = va_arg(va, SilcChannelEntry);
 
 			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-									channel->channel_name, sg->account);
+								      channel->channel_name, sg->account);
 			if (!convo)
 				break;
 
@@ -672,19 +651,19 @@
 			if (mode) {
 				silcpurple_get_chumode_string(mode, buf2, sizeof(buf2));
 				g_snprintf(buf, sizeof(buf),
-						_("<I>%s</I> set <I>%s's</I> modes to: %s"), name,
-						client_entry2->nickname, buf2);
+					   _("<I>%s</I> set <I>%s's</I> modes to: %s"), name,
+					   client_entry2->nickname, buf2);
 				if (mode & SILC_CHANNEL_UMODE_CHANFO)
 					flags |= PURPLE_CBFLAGS_FOUNDER;
 				if (mode & SILC_CHANNEL_UMODE_CHANOP)
 					flags |= PURPLE_CBFLAGS_OP;
 			} else {
 				g_snprintf(buf, sizeof(buf),
-						_("<I>%s</I> removed all <I>%s's</I> modes"), name,
-						client_entry2->nickname);
+					   _("<I>%s</I> removed all <I>%s's</I> modes"), name,
+					   client_entry2->nickname);
 			}
 			purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name,
-					buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
+					       buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
 			purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(convo), client_entry2->nickname, flags);
 			break;
 		}
@@ -702,7 +681,7 @@
 		channel = va_arg(va, SilcChannelEntry);
 
 		convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-								channel->channel_name, sg->account);
+							      channel->channel_name, sg->account);
 		if (!convo)
 			break;
 
@@ -713,15 +692,15 @@
 				   channel->channel_name, client_entry2->nickname,
 				   tmp ? tmp : "");
 			purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname,
-					     buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
+					       buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
 			serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)));
 		} else {
 			/* Remove user from channel */
 			g_snprintf(buf, sizeof(buf), _("Kicked by %s (%s)"),
 				   client_entry2->nickname, tmp ? tmp : "");
 			purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo),
-						   client_entry->nickname,
-						   buf);
+						     client_entry->nickname,
+						     buf);
 		}
 
 		break;
@@ -732,9 +711,6 @@
 		idtype = va_arg(va, int);
 		entry = va_arg(va, SilcClientEntry);
 
-		if (!client_entry->nickname)
-			break;
-
 		if (client_entry == conn->local_entry) {
 			if (idtype == SILC_ID_CLIENT) {
 				client_entry2 = (SilcClientEntry)entry;
@@ -761,7 +737,7 @@
 				if (!convo)
 					continue;
 				purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname,
-						     buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
+						       buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
 				serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)));
 			}
 			silc_hash_table_list_reset(&htl);
@@ -792,7 +768,7 @@
 				if (!convo)
 					continue;
 				purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo),
-							   client_entry->nickname, tmp);
+							     client_entry->nickname, tmp);
 			}
 			silc_hash_table_list_reset(&htl);
 		}
@@ -803,33 +779,23 @@
 		break;
 
 	case SILC_NOTIFY_TYPE_SERVER_SIGNOFF:
-		{
-			int i;
-			SilcClientEntry *clients;
-			SilcUInt32 clients_count;
-
-			(void)va_arg(va, void *);
-			clients = va_arg(va, SilcClientEntry *);
-			clients_count = va_arg(va, SilcUInt32);
-
-			for (i = 0; i < clients_count; i++) {
-				if (!clients[i]->nickname)
-					break;
+		(void)va_arg(va, void *);
+		list = va_arg(va, SilcDList);
 
-				/* Remove from all channels */
-				silc_hash_table_list(clients[i]->channels, &htl);
-				while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-					convo =
-						purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-											chu->channel->channel_name, sg->account);
-					if (!convo)
-						continue;
-					purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo),
-								   clients[i]->nickname,
-								   _("Server signoff"));
-				}
-				silc_hash_table_list_reset(&htl);
+		silc_dlist_start(list);
+		while ((client_entry = silc_dlist_get(list))) {
+			/* Remove from all channels */
+			silc_hash_table_list(client_entry->channels, &htl);
+			while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
+				convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
+									      chu->channel->channel_name, sg->account);
+				if (!convo)
+					continue;
+				purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo),
+							     client_entry->nickname,
+							     _("Server signoff"));
 			}
+			silc_hash_table_list_reset(&htl);
 		}
 		break;
 
@@ -837,8 +803,8 @@
 		{
 			SilcStatus error = va_arg(va, int);
 			purple_notify_error(gc, "Error Notify",
-					  silc_get_status_message(error),
-					  NULL);
+					    silc_get_status_message(error),
+					    NULL);
 		}
 		break;
 
@@ -909,8 +875,8 @@
 			}
 
 			silc_free(b->proto_data);
-			b->proto_data = silc_memdup(client_entry->id,
-						    sizeof(*client_entry->id));
+			b->proto_data = silc_memdup(&client_entry->id,
+						    sizeof(client_entry->id));
 			if (notify == SILC_NOTIFY_TYPE_NICK_CHANGE) {
 				break;
 			} else if (notify == SILC_NOTIFY_TYPE_UMODE_CHANGE) {
@@ -955,19 +921,20 @@
 }
 
 
-/* Command handler. This function is called always in the command function.
-   If error occurs it will be called as well. `conn' is the associated
-   client connection. `cmd_context' is the command context that was
-   originally sent to the command. `success' is FALSE if error occurred
-   during command. `command' is the command being processed. It must be
-   noted that this is not reply from server. This is merely called just
-   after application has called the command. Just to tell application
-   that the command really was processed. */
+/* Command handler. This function is called always after application has
+   called a command.  It will be called to indicate that the command
+   was processed.  It will also be called if error occurs while processing
+   the command.  The `success' indicates whether the command was sent
+   or if error occurred.  The `status' indicates the actual error.
+   The `argc' and `argv' are the command line arguments sent to the
+   command by application.  Note that, this is not reply to the command
+   from server, this is merely and indication to application that the
+   command was processed. */
 
 static void
 silc_command(SilcClient client, SilcClientConnection conn,
-	     SilcClientCommandContext cmd_context, bool success,
-	     SilcCommand command, SilcStatus status)
+	     SilcBool success, SilcCommand command, SilcStatus status,
+	     SilcUInt32 argc, unsigned char **argv)
 {
 	PurpleConnection *gc = client->application;
 	SilcPurple sg = gc->proto_data;
@@ -975,8 +942,7 @@
 	switch (command) {
 
 	case SILC_COMMAND_CMODE:
-		if (cmd_context->argc == 3 &&
-		    !strcmp((char *)cmd_context->argv[2], "+C"))
+		if (argc == 3 && !strcmp((char *)argv[2], "+C"))
 			sg->chpk = TRUE;
 		else
 			sg->chpk = FALSE;
@@ -1090,53 +1056,96 @@
 }
 #endif
 
-/* Command reply handler. This function is called always in the command reply
-   function. If error occurs it will be called as well. Normal scenario
-   is that it will be called after the received command data has been parsed
-   and processed. The function is used to pass the received command data to
-   the application.
 
-   `conn' is the associated client connection. `cmd_payload' is the command
-   payload data received from server and it can be ignored. It is provided
-   if the application would like to re-parse the received command data,
-   however, it must be noted that the data is parsed already by the library
-   thus the payload can be ignored. `success' is FALSE if error occurred.
-   In this case arguments are not sent to the application. The `status' is
-   the command reply status server returned. The `command' is the command
-   reply being processed. The function has variable argument list and each
-   command defines the number and type of arguments it passes to the
-   application (on error they are not sent). */
+/* Command reply handler.  Delivers a reply to command that was sent
+   earlier.  The `conn' is the associated client connection.  The `command'
+   indicates the command reply type.  If the `status' other than
+   SILC_STATUS_OK an error occurred.  In this case the `error' will indicate
+   the error.  It is possible to receive list of command replies and list
+   of errors.  In this case the `status' will indicate it is an list entry
+   (the `status' is SILC_STATUS_LIST_START, SILC_STATUS_LIST_ITEM and/or
+   SILC_STATUS_LIST_END).
+
+   The arguments received in `ap' are command specific.  See a separate
+   documentation in the Toolkit Reference Manual for the command reply
+   arguments. */
 
 static void
 silc_command_reply(SilcClient client, SilcClientConnection conn,
-		   SilcCommandPayload cmd_payload, bool success,
-		   SilcCommand command, SilcStatus status, ...)
+		   SilcCommand command, SilcStatus status,
+		   SilcStatus error, va_list ap)
 {
 	PurpleConnection *gc = client->application;
 	SilcPurple sg = gc->proto_data;
 	PurpleConversation *convo;
-	va_list vp;
-
-	va_start(vp, status);
 
 	switch (command) {
 	case SILC_COMMAND_JOIN:
 		{
-			SilcChannelEntry channel_entry;
+			SilcChannelEntry channel;
+			PurpleConversation *convo;
+			SilcHashTableList *user_list;
+			SilcChannelUser chu;
+			GList *users = NULL, *flags = NULL;
+			char tmp[256], *topic;
 
-			if (!success) {
+			if (status != SILC_STATUS_OK) {
 				purple_notify_error(gc, _("Join Chat"), _("Cannot join channel"),
-						  silc_get_status_message(status));
+						    silc_get_status_message(error));
 				return;
 			}
 
-			(void)va_arg(vp, char *);
-			channel_entry = va_arg(vp, SilcChannelEntry);
+			(void)va_arg(ap, char *);
+			channel = va_arg(ap, SilcChannelEntry);
+			(void)va_arg(ap, SilcUInt32);
+			user_list = va_arg(ap, SilcHashTableList *);
+			topic = va_arg(ap, char *);
+
+			/* Add channel to Purple */
+			channel->context = SILC_32_TO_PTR(++sg->channel_ids);
+			serv_got_joined_chat(gc, sg->channel_ids, channel->channel_name);
+			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
+								      channel->channel_name, sg->account);
+			if (!convo)
+			  return;
+
+			/* Add all users to channel */
+			while (silc_hash_table_get(user_list, NULL, (void *)&chu)) {
+			  PurpleConvChatBuddyFlags f = PURPLE_CBFLAGS_NONE;
+			  chu->context = SILC_32_TO_PTR(sg->channel_ids);
+
+			  if (chu->mode & SILC_CHANNEL_UMODE_CHANFO)
+			    f |= PURPLE_CBFLAGS_FOUNDER;
+			  if (chu->mode & SILC_CHANNEL_UMODE_CHANOP)
+			    f |= PURPLE_CBFLAGS_OP;
+			  users = g_list_append(users, g_strdup(chu->client->nickname));
+			  flags = g_list_append(flags, GINT_TO_POINTER(f));
 
-			/* Resolve users on channel */
-			silc_client_get_clients_by_channel(client, conn, channel_entry,
-							   silcpurple_chat_join_done,
-							   channel_entry);
+			  if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) {
+			    if (chu->client == conn->local_entry)
+				g_snprintf(tmp, sizeof(tmp),
+					   _("You are channel founder on <I>%s</I>"),
+					   channel->channel_name);
+			    else
+				g_snprintf(tmp, sizeof(tmp),
+					   _("Channel founder on <I>%s</I> is <I>%s</I>"),
+					   channel->channel_name, chu->client->nickname);
+
+			    purple_conversation_write(convo, NULL, tmp,
+						      PURPLE_MESSAGE_SYSTEM, time(NULL));
+			  }
+			}
+
+			purple_conv_chat_add_users(PURPLE_CONV_CHAT(convo), users, NULL, flags, FALSE);
+			g_list_free(users);
+			g_list_free(flags);
+
+			/* Set topic */
+			if (topic)
+			  purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, topic);
+
+			/* Set nick */
+			purple_conv_chat_set_nick(PURPLE_CONV_CHAT(convo), conn->local_entry->nickname);
 		}
 		break;
 
@@ -1148,31 +1157,29 @@
 
 	case SILC_COMMAND_WHOIS:
 		{
-			SilcUInt32 idle, mode;
-			SilcBuffer channels, user_modes;
+			SilcUInt32 idle, *user_modes;
+			SilcDList channels;
 			SilcClientEntry client_entry;
 			char tmp[1024], *tmp2;
 			char *moodstr, *statusstr, *contactstr, *langstr, *devicestr, *tzstr, *geostr;
 			PurpleNotifyUserInfo *user_info;
 
-			if (!success) {
+			if (status != SILC_STATUS_OK) {
 				purple_notify_error(gc, _("User Information"),
 						_("Cannot get user information"),
-						silc_get_status_message(status));
+						silc_get_status_message(error));
 				break;
 			}
 
-			client_entry = va_arg(vp, SilcClientEntry);
-			if (!client_entry->nickname)
-				break;
-			(void)va_arg(vp, char *);
-			(void)va_arg(vp, char *);
-			(void)va_arg(vp, char *);
-			channels = va_arg(vp, SilcBuffer);
-			mode = va_arg(vp, SilcUInt32);
-			idle = va_arg(vp, SilcUInt32);
-			(void)va_arg(vp, unsigned char *);
-			user_modes = va_arg(vp, SilcBuffer);
+			client_entry = va_arg(ap, SilcClientEntry);
+			(void)va_arg(ap, char *);
+			(void)va_arg(ap, char *);
+			(void)va_arg(ap, char *);
+			channels = va_arg(ap, SilcDList);
+			(void)va_arg(ap, SilcUInt32);
+			idle = va_arg(ap, SilcUInt32);
+			(void)va_arg(ap, unsigned char *);
+			user_modes = va_arg(ap, SilcUInt32 *);
 
 			user_info = purple_notify_user_info_new();
 			tmp2 = g_markup_escape_text(client_entry->nickname, -1);
@@ -1183,22 +1190,20 @@
 				purple_notify_user_info_add_pair(user_info, _("Real Name"), tmp2);
 				g_free(tmp2);
 			}
-			if (client_entry->username) {
-				tmp2 = g_markup_escape_text(client_entry->username, -1);
-				if (client_entry->hostname) {
-					gchar *tmp3;
-					tmp3 = g_strdup_printf("%s@%s", tmp2, client_entry->hostname);
-					purple_notify_user_info_add_pair(user_info, _("Username"), tmp3);
-					g_free(tmp3);
-				} else
-					purple_notify_user_info_add_pair(user_info, _("Username"), tmp2);
-				g_free(tmp2);
-			}
+			tmp2 = g_markup_escape_text(client_entry->username, -1);
+			if (*client_entry->hostname) {
+				gchar *tmp3;
+				tmp3 = g_strdup_printf("%s@%s", tmp2, client_entry->hostname);
+				purple_notify_user_info_add_pair(user_info, _("Username"), tmp3);
+				g_free(tmp3);
+			} else
+				purple_notify_user_info_add_pair(user_info, _("Username"), tmp2);
+			g_free(tmp2);
 
 			if (client_entry->mode) {
 				memset(tmp, 0, sizeof(tmp));
 				silcpurple_get_umode_string(client_entry->mode,
-						tmp, sizeof(tmp) - strlen(tmp));
+							    tmp, sizeof(tmp) - strlen(tmp));
 				purple_notify_user_info_add_pair(user_info, _("User Modes"), tmp);
 			}
 
@@ -1240,39 +1245,28 @@
 				g_free(geostr);
 			}
 
-			if (client_entry->server)
+			if (*client_entry->server)
 				purple_notify_user_info_add_pair(user_info, _("Server"), client_entry->server);
 
 			if (channels && user_modes) {
-				SilcUInt32 *umodes;
-				SilcDList list =
-					silc_channel_payload_parse_list(channels->data,
-							channels->len);
-				if (list && silc_get_mode_list(user_modes,
-							silc_dlist_count(list),
-							&umodes)) {
-					SilcChannelPayload entry;
-					int i = 0;
+				SilcChannelPayload entry;
+				int i = 0;
 
-					memset(tmp, 0, sizeof(tmp));
-					silc_dlist_start(list);
-					while ((entry = silc_dlist_get(list))
-							!= SILC_LIST_END) {
-						SilcUInt32 name_len;
-						char *m = silc_client_chumode_char(umodes[i++]);
-						char *name = (char *)silc_channel_get_name(entry, &name_len);
-						if (m)
-							silc_strncat(tmp, sizeof(tmp) - 1, m, strlen(m));
-						silc_strncat(tmp, sizeof(tmp) - 1, name, name_len);
-						silc_strncat(tmp, sizeof(tmp) - 1, "  ", 1);
-						silc_free(m);
-
-					}
-					tmp2 = g_markup_escape_text(tmp, -1);
-					purple_notify_user_info_add_pair(user_info, _("Currently on"), tmp2);
-					g_free(tmp2);
-					silc_free(umodes);
+				memset(tmp, 0, sizeof(tmp));
+				silc_dlist_start(channels);
+				while ((entry = silc_dlist_get(channels))) {
+					SilcUInt32 name_len;
+					char *m = silc_client_chumode_char(user_modes[i++]);
+					char *name = (char *)silc_channel_get_name(entry, &name_len);
+					if (m)
+						silc_strncat(tmp, sizeof(tmp) - 1, m, strlen(m));
+					silc_strncat(tmp, sizeof(tmp) - 1, name, name_len);
+					silc_strncat(tmp, sizeof(tmp) - 1, "  ", 1);
+					silc_free(m);
 				}
+				tmp2 = g_markup_escape_text(tmp, -1);
+				purple_notify_user_info_add_pair(user_info, _("Currently on"), tmp2);
+				g_free(tmp2);
 			}
 
 			if (client_entry->public_key) {
@@ -1297,7 +1291,7 @@
 						_("OK"), G_CALLBACK(silcpurple_whois_more),
 						_("_More..."), G_CALLBACK(silcpurple_whois_more), gc->account, NULL, NULL);
 			else
-#endif
+#endif /* 0 */
 			purple_notify_userinfo(gc, client_entry->nickname, user_info, NULL, NULL);
 			purple_notify_user_info_destroy(user_info);
 		}
@@ -1309,17 +1303,17 @@
 			char *nickname, *realname, *username, *tmp;
 			PurpleNotifyUserInfo *user_info;
 
-			if (!success) {
+			if (status != SILC_STATUS_OK) {
 				purple_notify_error(gc, _("User Information"),
 						  _("Cannot get user information"),
-						  silc_get_status_message(status));
+						  silc_get_status_message(error));
 				break;
 			}
 
-			client_entry = va_arg(vp, SilcClientEntry);
-			nickname = va_arg(vp, char *);
-			username = va_arg(vp, char *);
-			realname = va_arg(vp, char *);
+			client_entry = va_arg(ap, SilcClientEntry);
+			nickname = va_arg(ap, char *);
+			username = va_arg(ap, char *);
+			realname = va_arg(ap, char *);
 			if (!nickname)
 				break;
 
@@ -1334,7 +1328,7 @@
 			}
 			if (username) {
 				tmp = g_markup_escape_text(username, -1);
-				if (client_entry && client_entry->hostname) {
+				if (client_entry && *client_entry->hostname) {
 					gchar *tmp3;
 					tmp3 = g_strdup_printf("%s@%s", tmp, client_entry->hostname);
 					purple_notify_user_info_add_pair(user_info, _("Username"), tmp3);
@@ -1343,7 +1337,7 @@
 					purple_notify_user_info_add_pair(user_info, _("Username"), tmp);
 				g_free(tmp);
 			}
-			if (client_entry && client_entry->server)
+			if (client_entry && *client_entry->server)
 				purple_notify_user_info_add_pair(user_info, _("Server"), client_entry->server);
 
 
@@ -1367,10 +1361,23 @@
 		break;
 
 	case SILC_COMMAND_DETACH:
-		if (!success) {
-			purple_notify_error(gc, _("Detach From Server"), _("Cannot detach"),
-					  silc_get_status_message(status));
-			return;
+		{
+			const char *file;
+			SilcBuffer detach_data;
+
+			if (status != SILC_STATUS_OK) {
+			  purple_notify_error(gc, _("Detach From Server"), _("Cannot detach"),
+					      silc_get_status_message(error));
+			  return;
+			}
+
+			detach_data = va_arg(ap, SilcBuffer);
+
+			/* Save the detachment data to file. */
+			file = silcpurple_session_file(purple_account_get_username(sg->account));
+			g_unlink(file);
+			silc_file_writefile(file, (const char *)silc_buffer_data(detach_data),
+					    silc_buffer_len(detach_data));
 		}
 		break;
 
@@ -1378,19 +1385,19 @@
 		{
 			SilcChannelEntry channel;
 
-			if (!success) {
+			if (status != SILC_STATUS_OK) {
 				purple_notify_error(gc, _("Topic"), _("Cannot set topic"),
-						  silc_get_status_message(status));
+						    silc_get_status_message(error));
 				return;
 			}
 
-			channel = va_arg(vp, SilcChannelEntry);
+			channel = va_arg(ap, SilcChannelEntry);
 
 			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-									channel->channel_name, sg->account);
+								      channel->channel_name, sg->account);
 			if (!convo) {
 				purple_debug_error("silc", "Got a topic for %s, which doesn't exist\n",
-								 channel->channel_name);
+						   channel->channel_name);
 				break;
 			}
 
@@ -1402,39 +1409,37 @@
 
 	case SILC_COMMAND_NICK:
 		{
-			/* I don't think we should need to do this because the server should
-			 * be sending a SILC_NOTIFY_TYPE_NICK_CHANGE when we change our own
-			 * nick, but it isn't, so we deal with it here instead. Stu. */
 			SilcClientEntry local_entry;
 			SilcHashTableList htl;
 			SilcChannelUser chu;
-			const char *oldnick;
+			const char *oldnick, *newnick;
 
-			if (!success) {
+			if (status != SILC_STATUS_OK) {
 				purple_notify_error(gc, _("Nick"), _("Failed to change nickname"),
-						silc_get_status_message(status));
+						    silc_get_status_message(error));
 				return;
 			}
 
-			local_entry = va_arg(vp, SilcClientEntry);
+			local_entry = va_arg(ap, SilcClientEntry);
+			newnick = va_arg(ap, char *);
 
 			/* Change nick on all channels */
 			silc_hash_table_list(local_entry->channels, &htl);
 			while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
 				convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
-									chu->channel->channel_name, sg->account);
+									      chu->channel->channel_name, sg->account);
 				if (!convo)
 					continue;
 				oldnick = purple_conv_chat_get_nick(PURPLE_CONV_CHAT(convo));
-				if (strcmp(oldnick, purple_normalize(purple_conversation_get_account(convo), local_entry->nickname))) {
+				if (strcmp(oldnick, purple_normalize(purple_conversation_get_account(convo), newnick))) {
 					purple_conv_chat_rename_user(PURPLE_CONV_CHAT(convo),
-							oldnick, local_entry->nickname);
-					purple_conv_chat_set_nick(PURPLE_CONV_CHAT(convo), local_entry->nickname);
+								     oldnick, newnick);
+					purple_conv_chat_set_nick(PURPLE_CONV_CHAT(convo), newnick);
 				}
 			}
 			silc_hash_table_list_reset(&htl);
 
-			purple_connection_set_display_name(gc, local_entry->nickname);
+			purple_connection_set_display_name(gc, newnick);
 		}
 		break;
 
@@ -1447,34 +1452,34 @@
 			if (sg->roomlist_canceled)
 				break;
 
-			if (!success) {
+			if (error != SILC_STATUS_OK) {
 				purple_notify_error(gc, _("Error"), _("Error retrieving room list"),
-						  silc_get_status_message(status));
+						    silc_get_status_message(error));
 				purple_roomlist_set_in_progress(sg->roomlist, FALSE);
 				purple_roomlist_unref(sg->roomlist);
 				sg->roomlist = NULL;
 				return;
 			}
 
-			(void)va_arg(vp, SilcChannelEntry);
-			name = va_arg(vp, char *);
+			(void)va_arg(ap, SilcChannelEntry);
+			name = va_arg(ap, char *);
 			if (!name) {
 				purple_notify_error(gc, _("Roomlist"), _("Cannot get room list"),
-						  silc_get_status_message(status));
+						    _("Network is empty"));
 				purple_roomlist_set_in_progress(sg->roomlist, FALSE);
 				purple_roomlist_unref(sg->roomlist);
 				sg->roomlist = NULL;
 				return;
 			}
-			topic = va_arg(vp, char *);
-			usercount = va_arg(vp, int);
+			topic = va_arg(ap, char *);
+			usercount = va_arg(ap, int);
 
 			room = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM, name, NULL);
 			purple_roomlist_room_add_field(sg->roomlist, room, name);
 			purple_roomlist_room_add_field(sg->roomlist, room,
-						     SILC_32_TO_PTR(usercount));
+						       SILC_32_TO_PTR(usercount));
 			purple_roomlist_room_add_field(sg->roomlist, room,
-						     topic ? topic : "");
+						       topic ? topic : "");
 			purple_roomlist_room_add(sg->roomlist, room);
 
 			if (status == SILC_STATUS_LIST_END ||
@@ -1490,21 +1495,21 @@
 		{
 			SilcPublicKey public_key;
 
-			if (!success) {
+			if (status != SILC_STATUS_OK) {
 				purple_notify_error(gc, _("Get Public Key"),
-						  _("Cannot fetch the public key"),
-						  silc_get_status_message(status));
+						    _("Cannot fetch the public key"),
+						    silc_get_status_message(error));
 				return;
 			}
 
-			(void)va_arg(vp, SilcUInt32);
-			(void)va_arg(vp, void *);
-			public_key = va_arg(vp, SilcPublicKey);
+			(void)va_arg(ap, SilcUInt32);
+			(void)va_arg(ap, void *);
+			public_key = va_arg(ap, SilcPublicKey);
 
 			if (!public_key)
 				purple_notify_error(gc, _("Get Public Key"),
-						  _("Cannot fetch the public key"),
-						  _("No public key was received"));
+						    _("Cannot fetch the public key"),
+						    _("No public key was received"));
 		}
 		break;
 
@@ -1515,16 +1520,16 @@
 			char *server_info;
 			char tmp[256];
 
-			if (!success) {
+			if (status != SILC_STATUS_OK) {
 				purple_notify_error(gc, _("Server Information"),
-						  _("Cannot get server information"),
-						  silc_get_status_message(status));
+						    _("Cannot get server information"),
+						    silc_get_status_message(error));
 				return;
 			}
 
-			(void)va_arg(vp, SilcServerEntry);
-			server_name = va_arg(vp, char *);
-			server_info = va_arg(vp, char *);
+			(void)va_arg(ap, SilcServerEntry);
+			server_name = va_arg(ap, char *);
+			server_info = va_arg(ap, char *);
 
 			if (server_name && server_info) {
 				g_snprintf(tmp, sizeof(tmp), "Server: %s\n%s",
@@ -1536,94 +1541,73 @@
 
 	case SILC_COMMAND_STATS:
 		{
-			SilcUInt32 starttime, uptime, my_clients, my_channels, my_server_ops,
-			my_router_ops, cell_clients, cell_channels, cell_servers,
-			clients, channels, servers, routers, server_ops, router_ops;
-			SilcUInt32 buffer_length;
-			SilcBufferStruct buf;
-
-			unsigned char *server_stats;
+			SilcClientStats *stats;
 			char *msg;
 
-			if (!success) {
+			if (status != SILC_STATUS_OK) {
 				purple_notify_error(gc, _("Server Statistics"),
-						_("Cannot get server statistics"),
-						silc_get_status_message(status));
+						    _("Cannot get server statistics"),
+						    silc_get_status_message(error));
 				return;
 			}
 
-			server_stats = va_arg(vp, unsigned char *);
-			buffer_length = va_arg(vp, SilcUInt32);
-			if (!server_stats || !buffer_length) {
-				purple_notify_error(gc, _("Server Statistics"),
-						_("No server statistics available"), NULL);
-				break;
-			}
-			silc_buffer_set(&buf, server_stats, buffer_length);
-			silc_buffer_unformat(&buf,
-					SILC_STR_UI_INT(&starttime),
-					SILC_STR_UI_INT(&uptime),
-					SILC_STR_UI_INT(&my_clients),
-					SILC_STR_UI_INT(&my_channels),
-					SILC_STR_UI_INT(&my_server_ops),
-					SILC_STR_UI_INT(&my_router_ops),
-					SILC_STR_UI_INT(&cell_clients),
-					SILC_STR_UI_INT(&cell_channels),
-					SILC_STR_UI_INT(&cell_servers),
-					SILC_STR_UI_INT(&clients),
-					SILC_STR_UI_INT(&channels),
-					SILC_STR_UI_INT(&servers),
-					SILC_STR_UI_INT(&routers),
-					SILC_STR_UI_INT(&server_ops),
-					SILC_STR_UI_INT(&router_ops),
-					SILC_STR_END);
+			stats = va_arg(ap, SilcClientStats *);
 
 			msg = g_strdup_printf(_("Local server start time: %s\n"
-					"Local server uptime: %s\n"
-					"Local server clients: %d\n"
-					"Local server channels: %d\n"
-					"Local server operators: %d\n"
-					"Local router operators: %d\n"
-					"Local cell clients: %d\n"
-					"Local cell channels: %d\n"
-					"Local cell servers: %d\n"
-					"Total clients: %d\n"
-					"Total channels: %d\n"
-					"Total servers: %d\n"
-					"Total routers: %d\n"
-					"Total server operators: %d\n"
-					"Total router operators: %d\n"),
-					silc_get_time(starttime),
-					purple_str_seconds_to_string((int)uptime),
-					(int)my_clients, (int)my_channels, (int)my_server_ops, (int)my_router_ops,
-					(int)cell_clients, (int)cell_channels, (int)cell_servers,
-					(int)clients, (int)channels, (int)servers, (int)routers,
-					(int)server_ops, (int)router_ops);
+						"Local server uptime: %s\n"
+						"Local server clients: %d\n"
+						"Local server channels: %d\n"
+						"Local server operators: %d\n"
+						"Local router operators: %d\n"
+						"Local cell clients: %d\n"
+						"Local cell channels: %d\n"
+						"Local cell servers: %d\n"
+						"Total clients: %d\n"
+						"Total channels: %d\n"
+						"Total servers: %d\n"
+						"Total routers: %d\n"
+						"Total server operators: %d\n"
+						"Total router operators: %d\n"),
+					      silc_time_string(stats->starttime),
+					      purple_str_seconds_to_string((int)stats->uptime),
+					      (int)stats->my_clients,
+					      (int)stats->my_channels,
+					      (int)stats->my_server_ops,
+					      (int)stats->my_router_ops,
+					      (int)stats->cell_clients,
+					      (int)stats->cell_channels,
+					      (int)stats->cell_servers,
+					      (int)stats->clients,
+					      (int)stats->channels,
+					      (int)stats->servers,
+					      (int)stats->routers,
+					      (int)stats->server_ops,
+					      (int)stats->router_ops);
 
 			purple_notify_info(gc, NULL,
-					_("Network Statistics"), msg);
+					   _("Network Statistics"), msg);
 			g_free(msg);
 		}
 		break;
 
 	case SILC_COMMAND_PING:
 		{
-			if (!success) {
+			if (status != SILC_STATUS_OK) {
 				purple_notify_error(gc, _("Ping"), _("Ping failed"),
-								  silc_get_status_message(status));
+						    silc_get_status_message(error));
 				return;
 			}
 
 			purple_notify_info(gc, _("Ping"), _("Ping reply received from server"),
-							 NULL);
+					   NULL);
 		}
 		break;
 
 	case SILC_COMMAND_KILL:
-		if (!success) {
+		if (status != SILC_STATUS_OK) {
 			purple_notify_error(gc, _("Kill User"),
-					  _("Could not kill user"),
-					  silc_get_status_message(status));
+					    _("Could not kill user"),
+					    silc_get_status_message(error));
 			return;
 		}
 		break;
@@ -1631,188 +1615,108 @@
 	case SILC_COMMAND_CMODE:
 		{
 			SilcChannelEntry channel_entry;
-			SilcBuffer channel_pubkeys;
+			SilcDList channel_pubkeys, list;
+			SilcArgumentDecodedList e;
 
-			if (!success)
+			if (status != SILC_STATUS_OK)
 				return;
 
-			channel_entry = va_arg(vp, SilcChannelEntry);
-			(void)va_arg(vp, SilcUInt32);
-			(void)va_arg(vp, SilcPublicKey);
-			channel_pubkeys = va_arg(vp, SilcBuffer);
+			channel_entry = va_arg(ap, SilcChannelEntry);
+			(void)va_arg(ap, SilcUInt32);
+			(void)va_arg(ap, SilcPublicKey);
+			channel_pubkeys = va_arg(ap, SilcDList);
+
+			if (!sg->chpk)
+				break;
+
+			list = silc_dlist_init();
 
-			if (sg->chpk)
-				silcpurple_chat_chauth_show(sg, channel_entry, channel_pubkeys);
+			if (channel_pubkeys) {
+			  silc_dlist_start(channel_pubkeys);
+			  while ((e = silc_dlist_get(channel_pubkeys))) {
+				if (e->arg_type == 0x00 ||
+				    e->arg_type == 0x03)
+				  silc_dlist_add(list, silc_pkcs_public_key_copy(e->argument));
+			  }
+			}
+			silcpurple_chat_chauth_show(sg, channel_entry, list);
+		}
+		break;
+
+	case SILC_COMMAND_WATCH:
+		if (status != SILC_STATUS_OK) {
+			purple_notify_error(gc, _("WATCH"), _("Cannot watch user"),
+					    silc_get_status_message(error));
+			return;
 		}
 		break;
 
 	default:
-		if (success)
+		if (status == SILC_STATUS_OK)
 			purple_debug_info("silc", "Unhandled command: %d (succeeded)\n", command);
 		else
 			purple_debug_info("silc", "Unhandled command: %d (failed: %s)\n", command,
-							silc_get_status_message(status));
+					  silc_get_status_message(error));
 		break;
 	}
-
-	va_end(vp);
 }
 
-
-/* Called to indicate that connection was either successfully established
-   or connecting failed.  This is also the first time application receives
-   the SilcClientConnection object which it should save somewhere.
-   If the `success' is FALSE the application must always call the function
-   silc_client_close_connection. */
-
-static void
-silc_connected(SilcClient client, SilcClientConnection conn,
-	       SilcClientConnectionStatus status)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg;
-	gboolean reject_watch, block_invites, block_ims;
-
-	if (gc == NULL) {
-		silc_client_close_connection(client, conn);
-		return;
-	}
-	sg = gc->proto_data;
-
-	switch (status) {
-	case SILC_CLIENT_CONN_SUCCESS:
-	case SILC_CLIENT_CONN_SUCCESS_RESUME:
-		purple_connection_set_state(gc, PURPLE_CONNECTED);
-
-		/* Send the server our buddy list */
-		silcpurple_send_buddylist(gc);
-
-		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
-
-		/* Send any UMODEs configured for account */
-		reject_watch = purple_account_get_bool(sg->account, "reject-watch", FALSE);
-		block_invites = purple_account_get_bool(sg->account, "block-invites", FALSE);
-		block_ims = purple_account_get_bool(sg->account, "block-ims", FALSE);
-		if (reject_watch || block_invites || block_ims) {
-			char m[5];
-			g_snprintf(m, sizeof(m), "+%s%s%s",
-					   reject_watch ? "w" : "",
-					   block_invites ? "I" : "",
-					   block_ims ? "P" : "");
-			silc_client_command_call(sg->client, sg->conn, NULL,
-					"UMODE", m, NULL);
-		}
+/* Generic command reply callback for silc_client_command_send.  Simply
+   calls the default command_reply client operation callback */
 
-		return;
-		break;
-	case SILC_CLIENT_CONN_ERROR:
-		purple_connection_error(gc, _("Error during connecting to SILC Server"));
-		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
-		break;
-
-	case SILC_CLIENT_CONN_ERROR_KE:
-		purple_connection_error(gc, _("Key Exchange failed"));
-		break;
-
-	case SILC_CLIENT_CONN_ERROR_AUTH:
-		purple_connection_error(gc, _("Authentication failed"));
-		break;
-
-	case SILC_CLIENT_CONN_ERROR_RESUME:
-		purple_connection_error(gc,
-				      _("Resuming detached session failed. "
-					"Press Reconnect to create new connection."));
-		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
-		break;
-
-	case SILC_CLIENT_CONN_ERROR_TIMEOUT:
-		purple_connection_error(gc, _("Connection Timeout"));
-		break;
-	}
-
-	/* Error */
-	sg->conn = NULL;
-	silc_client_close_connection(client, conn);
-}
-
-
-/* Called to indicate that connection was disconnected to the server.
-   The `status' may tell the reason of the disconnection, and if the
-   `message' is non-NULL it may include the disconnection message
-   received from server. */
-
-static void
-silc_disconnected(SilcClient client, SilcClientConnection conn,
-		  SilcStatus status, const char *message)
+SilcBool silcpurple_command_reply(SilcClient client, SilcClientConnection conn,
+				  SilcCommand command, SilcStatus status,
+				  SilcStatus error, void *context, va_list ap)
 {
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
-
-	if (sg->resuming && !sg->detaching)
-		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
-
-	sg->conn = NULL;
-
-	/* Close the connection */
-	if (!sg->detaching)
-		purple_connection_error(gc, _("Disconnected by server"));
-	else
-		/* TODO: Does this work correctly? Maybe we need to set wants_to_die? */
-		purple_account_disconnect(purple_connection_get_account(gc));
+  silc_command_reply(client, conn, command, status, error, ap);
+  return TRUE;
 }
 
 
 typedef struct {
-	SilcGetAuthMeth completion;
+        union {
+	  SilcAskPassphrase ask_pass;
+	  SilcGetAuthMeth get_auth;
+	} u;
 	void *context;
-} *SilcPurpleGetAuthMethod;
-
-/* Callback called when we've received the authentication method information
-   from the server after we've requested it. */
-
-static void silc_get_auth_method_callback(SilcClient client,
-					  SilcClientConnection conn,
-					  SilcAuthMethod auth_meth,
-					  void *context)
-{
-	SilcPurpleGetAuthMethod internal = context;
+} *SilcPurpleAskPassphrase;
 
-	switch (auth_meth) {
-	case SILC_AUTH_NONE:
-		/* No authentication required. */
-		(*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
-		break;
+static void
+silc_ask_auth_password_cb(const unsigned char *passphrase,
+			  SilcUInt32 passphrase_len, void *context)
+{
+	SilcPurpleAskPassphrase internal = context;
 
-	case SILC_AUTH_PASSWORD:
-		/* By returning NULL here the library will ask the passphrase from us
-		   by calling the silc_ask_passphrase. */
-		(*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
-		break;
-
-	case SILC_AUTH_PUBLIC_KEY:
-		/* Do not get the authentication data now, the library will generate
-		   it using our default key, if we do not provide it here. */
-		(*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
-		break;
-	}
-
+	if (!passphrase || !(*passphrase))
+	  internal->u.get_auth(SILC_AUTH_NONE, NULL, 0, internal->context);
+	else
+	  internal->u.get_auth(SILC_AUTH_PASSWORD,
+			       (unsigned char *)passphrase,
+			       passphrase_len, internal->context);
 	silc_free(internal);
 }
 
 /* Find authentication method and authentication data by hostname and
-   port. The hostname may be IP address as well. When the authentication
-   method has been resolved the `completion' callback with the found
-   authentication method and authentication data is called. The `conn'
-   may be NULL. */
+   port. The hostname may be IP address as well. The `auth_method' is
+   the authentication method the remote connection requires.  It is
+   however possible that remote accepts also some other authentication
+   method.  Application should use the method that may have been
+   configured for this connection.  If none has been configured it should
+   use the required `auth_method'.  If the `auth_method' is
+   SILC_AUTH_NONE, server does not require any authentication or the
+   required authentication method is not known.  The `completion'
+   callback must be called to deliver the chosen authentication method
+   and data. The `conn' may be NULL. */
 
 static void
 silc_get_auth_method(SilcClient client, SilcClientConnection conn,
 		     char *hostname, SilcUInt16 port,
+		     SilcAuthMethod auth_method,
 		     SilcGetAuthMeth completion, void *context)
 {
 	PurpleConnection *gc = client->application;
 	SilcPurple sg = gc->proto_data;
-	SilcPurpleGetAuthMethod internal;
+	SilcPurpleAskPassphrase internal;
 	const char *password;
 
 	/* Progress */
@@ -1821,72 +1725,71 @@
 	else
 		purple_connection_update_progress(gc, _("Authenticating connection"), 4, 5);
 
-	/* Check configuration if we have this connection configured.  If we
-	   have then return that data immediately, as it's faster way. */
-	if (purple_account_get_bool(sg->account, "pubkey-auth", FALSE)) {
-		completion(TRUE, SILC_AUTH_PUBLIC_KEY, NULL, 0, context);
+	/* Check configuration if we have this connection configured. */
+	if (auth_method == SILC_AUTH_PUBLIC_KEY &&
+	    purple_account_get_bool(sg->account, "pubkey-auth", FALSE)) {
+		completion(SILC_AUTH_PUBLIC_KEY, NULL, 0, context);
 		return;
 	}
-	password = purple_connection_get_password(gc);
-	if (password && *password) {
-		completion(TRUE, SILC_AUTH_PASSWORD, (unsigned char *)password, strlen(password), context);
+	if (auth_method == SILC_AUTH_PASSWORD) {
+		password = purple_connection_get_password(gc);
+		if (password && *password) {
+		  completion(SILC_AUTH_PASSWORD, (unsigned char *)password, strlen(password), context);
+		  return;
+		}
+
+		/* Ask password from user */
+		internal = silc_calloc(1, sizeof(*internal));
+		if (!internal)
+		  return;
+		internal->u.get_auth = completion;
+		internal->context = context;
+		silc_ask_passphrase(client, conn, silc_ask_auth_password_cb,
+				    internal);
 		return;
 	}
 
-	/* Resolve the authentication method from server, as we may not know it. */
-	internal = silc_calloc(1, sizeof(*internal));
-	if (!internal)
-		return;
-	internal->completion = completion;
-	internal->context = context;
-	silc_client_request_authentication_method(client, conn,
-						  silc_get_auth_method_callback,
-						  internal);
+	completion(SILC_AUTH_NONE, NULL, 0, context);
 }
 
 
-/* Verifies received public key. The `conn_type' indicates which entity
-   (server, client etc.) has sent the public key. If user decides to trust
-   the application may save the key as trusted public key for later
-   use. The `completion' must be called after the public key has been
-   verified. */
+/* Called to verify received public key. The `conn_type' indicates which
+   entity (server or client) has sent the public key. If user decides to
+   trust the key the application may save the key as trusted public key for
+   later use. The `completion' must be called after the public key has
+   been verified. */
 
 static void
 silc_verify_public_key(SilcClient client, SilcClientConnection conn,
-		       SilcSocketType conn_type, unsigned char *pk,
-		       SilcUInt32 pk_len, SilcSKEPKType pk_type,
+		       SilcConnectionType conn_type,
+		       SilcPublicKey public_key,
 		       SilcVerifyPublicKey completion, void *context)
 {
 	PurpleConnection *gc = client->application;
 	SilcPurple sg = gc->proto_data;
 
-	if (!sg->conn && (conn_type == SILC_SOCKET_TYPE_SERVER ||
-			  conn_type == SILC_SOCKET_TYPE_ROUTER)) {
+	if (!sg->conn && (conn_type == SILC_CONN_SERVER ||
+			  conn_type == SILC_CONN_ROUTER)) {
 		/* Progress */
 		if (sg->resuming)
 			purple_connection_update_progress(gc, _("Resuming session"), 3, 5);
 		else
 			purple_connection_update_progress(gc, _("Verifying server public key"),
-							3, 5);
+							  3, 5);
 	}
 
 	/* Verify public key */
-	silcpurple_verify_public_key(client, conn, NULL, conn_type, pk,
-				   pk_len, pk_type, completion, context);
+	silcpurple_verify_public_key(client, conn, NULL, conn_type,
+				     public_key, completion, context);
 }
 
-typedef struct {
-	SilcAskPassphrase completion;
-	void *context;
-} *SilcPurpleAskPassphrase;
-
 static void
 silc_ask_passphrase_cb(SilcPurpleAskPassphrase internal, const char *passphrase)
 {
 	if (!passphrase || !(*passphrase))
-		internal->completion(NULL, 0, internal->context);
+		internal->u.ask_pass(NULL, 0, internal->context);
 	else
-		internal->completion((unsigned char *)passphrase,
+		internal->u.ask_pass((unsigned char *)passphrase,
 				     strlen(passphrase), internal->context);
 	silc_free(internal);
 }
@@ -1905,97 +1808,32 @@
 
 	if (!internal)
 		return;
-	internal->completion = completion;
+	internal->u.ask_pass = completion;
 	internal->context = context;
 	purple_request_input(gc, _("Passphrase"), NULL,
-			   _("Passphrase required"), NULL, FALSE, TRUE, NULL,
-			   _("OK"), G_CALLBACK(silc_ask_passphrase_cb),
-			   _("Cancel"), G_CALLBACK(silc_ask_passphrase_cb),
-			   purple_connection_get_account(gc), NULL, NULL, internal);
+			     _("Passphrase required"), NULL, FALSE, TRUE, NULL,
+			     _("OK"), G_CALLBACK(silc_ask_passphrase_cb),
+			     _("Cancel"), G_CALLBACK(silc_ask_passphrase_cb),
+			     purple_connection_get_account(gc), NULL, NULL, internal);
 }
 
 
-/* Notifies application that failure packet was received.  This is called
-   if there is some protocol active in the client.  The `protocol' is the
-   protocol context.  The `failure' is opaque pointer to the failure
-   indication.  Note, that the `failure' is protocol dependant and
-   application must explicitly cast it to correct type.  Usually `failure'
-   is 32 bit failure type (see protocol specs for all protocol failure
-   types). */
+/* Called to indicate that incoming key agreement request has been
+   received.  If the application wants to perform key agreement it may
+   call silc_client_perform_key_agreement to initiate key agreement or
+   silc_client_send_key_agreement to provide connection point to the
+   remote client in case the `hostname' is NULL.  If key agreement is
+   not desired this request can be ignored.  The `protocol' is either
+   value 0 for TCP or value 1 for UDP. */
 
 static void
-silc_failure(SilcClient client, SilcClientConnection conn,
-	     SilcProtocol protocol, void *failure)
+silc_key_agreement(SilcClient client, SilcClientConnection conn,
+		   SilcClientEntry client_entry,
+		   const char *hostname, SilcUInt16 protocol,
+		   SilcUInt16 port)
 {
-	PurpleConnection *gc = client->application;
-	char buf[128];
-
-	memset(buf, 0, sizeof(buf));
-
-	if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
-		SilcSKEStatus status = (SilcSKEStatus)SILC_PTR_TO_32(failure);
-
-		if (status == SILC_SKE_STATUS_BAD_VERSION)
-			g_snprintf(buf, sizeof(buf),
-				   _("Failure: Version mismatch, upgrade your client"));
-		if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY)
-			g_snprintf(buf, sizeof(buf),
-				   _("Failure: Remote does not trust/support your public key"));
-		if (status == SILC_SKE_STATUS_UNKNOWN_GROUP)
-			g_snprintf(buf, sizeof(buf),
-				   _("Failure: Remote does not support proposed KE group"));
-		if (status == SILC_SKE_STATUS_UNKNOWN_CIPHER)
-			g_snprintf(buf, sizeof(buf),
-				   _("Failure: Remote does not support proposed cipher"));
-		if (status == SILC_SKE_STATUS_UNKNOWN_PKCS)
-			g_snprintf(buf, sizeof(buf),
-				   _("Failure: Remote does not support proposed PKCS"));
-		if (status == SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION)
-			g_snprintf(buf, sizeof(buf),
-				   _("Failure: Remote does not support proposed hash function"));
-		if (status == SILC_SKE_STATUS_UNKNOWN_HMAC)
-			g_snprintf(buf, sizeof(buf),
-				   _("Failure: Remote does not support proposed HMAC"));
-		if (status == SILC_SKE_STATUS_INCORRECT_SIGNATURE)
-			g_snprintf(buf, sizeof(buf), _("Failure: Incorrect signature"));
-		if (status == SILC_SKE_STATUS_INVALID_COOKIE)
-			g_snprintf(buf, sizeof(buf), _("Failure: Invalid cookie"));
-
-		/* Show the error on the progress bar.  A more generic error message
-		   is going to be showed to user after this in the silc_connected. */
-		purple_connection_update_progress(gc, buf, 2, 5);
-	}
-
-	if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
-		SilcUInt32 err = SILC_PTR_TO_32(failure);
-
-		if (err == SILC_AUTH_FAILED)
-			g_snprintf(buf, sizeof(buf), _("Failure: Authentication failed"));
-
-		/* Show the error on the progress bar.  A more generic error message
-		   is going to be showed to user after this in the silc_connected. */
-		purple_connection_update_progress(gc, buf, 4, 5);
-	}
-}
-
-/* Asks whether the user would like to perform the key agreement protocol.
-   This is called after we have received an key agreement packet or an
-   reply to our key agreement packet. This returns TRUE if the user wants
-   the library to perform the key agreement protocol and FALSE if it is not
-   desired (application may start it later by calling the function
-   silc_client_perform_key_agreement). If TRUE is returned also the
-   `completion' and `context' arguments must be set by the application. */
-
-static bool
-silc_key_agreement(SilcClient client, SilcClientConnection conn,
-		   SilcClientEntry client_entry, const char *hostname,
-		   SilcUInt16 port, SilcKeyAgreementCallback *completion,
-		   void **context)
-{
-	silcpurple_buddy_keyagr_request(client, conn, client_entry, hostname, port);
-	*completion = NULL;
-	*context = NULL;
-	return FALSE;
+	silcpurple_buddy_keyagr_request(client, conn, client_entry,
+					hostname, port, protocol);
 }
 
 
@@ -2012,39 +1850,7 @@
 	 const char *hostname, SilcUInt16 port)
 {
 	silcpurple_ftp_request(client, conn, client_entry, session_id,
-			     hostname, port);
-}
-
-
-/* Delivers SILC session detachment data indicated by `detach_data' to the
-   application.  If application has issued SILC_COMMAND_DETACH command
-   the client session in the SILC network is not quit.  The client remains
-   in the network but is detached.  The detachment data may be used later
-   to resume the session in the SILC Network.  The appliation is
-   responsible of saving the `detach_data', to for example in a file.
-
-   The detachment data can be given as argument to the functions
-   silc_client_connect_to_server, or silc_client_add_connection when
-   creating connection to remote server, inside SilcClientConnectionParams
-   structure.  If it is provided the client library will attempt to resume
-   the session in the network.  After the connection is created
-   successfully, the application is responsible of setting the user
-   interface for user into the same state it was before detaching (showing
-   same channels, channel modes, etc).  It can do this by fetching the
-   information (like joined channels) from the client library. */
-
-static void
-silc_detach(SilcClient client, SilcClientConnection conn,
-	    const unsigned char *detach_data, SilcUInt32 detach_data_len)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = gc->proto_data;
-	const char *file;
-
-	/* Save the detachment data to file. */
-	file = silcpurple_session_file(purple_account_get_username(sg->account));
-	g_unlink(file);
-	silc_file_writefile(file, (char *)detach_data, detach_data_len);
+			       hostname, port);
 }
 
 SilcClientOperations ops = {
@@ -2054,13 +1860,9 @@
 	silc_notify,
 	silc_command,
 	silc_command_reply,
-	silc_connected,
-	silc_disconnected,
 	silc_get_auth_method,
 	silc_verify_public_key,
 	silc_ask_passphrase,
-	silc_failure,
 	silc_key_agreement,
-	silc_ftp,
-	silc_detach
+	silc_ftp
 };
--- a/libpurple/protocols/silc/pk.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/silc/pk.c	Mon Jun 18 01:48:35 2007 +0000
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2004 Pekka Riikonen
+  Copyright (C) 2004 - 2007 Pekka Riikonen
 
   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
@@ -17,7 +17,7 @@
 
 */
 
-#include "silcincludes.h"
+#include "silc.h"
 #include "silcclient.h"
 #include "silcpurple.h"
 
@@ -31,18 +31,16 @@
 	char *entity_name;
 	char *fingerprint;
 	char *babbleprint;
-	unsigned char *pk;
-	SilcUInt32 pk_len;
-	SilcSKEPKType pk_type;
+	SilcPublicKey public_key;
 	SilcVerifyPublicKey completion;
 	void *context;
 	gboolean changed;
 } *PublicKeyVerify;
 
 static void silcpurple_verify_ask(const char *entity,
-				const char *fingerprint,
-				const char *babbleprint,
-				PublicKeyVerify verify);
+				  const char *fingerprint,
+				  const char *babbleprint,
+				  PublicKeyVerify verify);
 
 static void silcpurple_verify_cb(PublicKeyVerify verify, gint id)
 {
@@ -54,8 +52,8 @@
 			verify->completion(TRUE, verify->context);
 
 		/* Save the key for future checking */
-		silc_pkcs_save_public_key_data(verify->filename, verify->pk,
-					       verify->pk_len, SILC_PKCS_FILE_PEM);
+		silc_pkcs_save_public_key(verify->filename, verify->public_key,
+					  SILC_PKCS_FILE_BASE64);
 	}
 
 	silc_free(verify->filename);
@@ -63,7 +61,7 @@
 	silc_free(verify->entity_name);
 	silc_free(verify->fingerprint);
 	silc_free(verify->babbleprint);
-	silc_free(verify->pk);
+	silc_pkcs_public_key_free(verify->public_key);
 	silc_free(verify);
 }
 
@@ -74,27 +72,23 @@
 	   should have option for the dialogs whether the buttons close them
 	   or not. */
 	silcpurple_verify_ask(verify->entity, verify->fingerprint,
-			    verify->babbleprint, verify);
+			      verify->babbleprint, verify);
 }
 
 static void silcpurple_verify_details(PublicKeyVerify verify, gint id)
 {
-	SilcPublicKey public_key;
 	PurpleConnection *gc = verify->client->application;
 	SilcPurple sg = gc->proto_data;
 
-	silc_pkcs_public_key_decode(verify->pk, verify->pk_len,
-				    &public_key);
-	silcpurple_show_public_key(sg, verify->entity_name, public_key,
-				 G_CALLBACK(silcpurple_verify_details_cb),
-				 verify);
-	silc_pkcs_public_key_free(public_key);
+	silcpurple_show_public_key(sg, verify->entity_name, verify->public_key,
+				   G_CALLBACK(silcpurple_verify_details_cb),
+				   verify);
 }
 
 static void silcpurple_verify_ask(const char *entity,
-				const char *fingerprint,
-				const char *babbleprint,
-				PublicKeyVerify verify)
+				  const char *fingerprint,
+				  const char *babbleprint,
+				  PublicKeyVerify verify)
 {
 	PurpleConnection *gc = verify->client->application;
 	char tmp[256], tmp2[256];
@@ -114,18 +108,17 @@
 		     "%s\n%s\n"), entity, fingerprint, babbleprint);
 
 	purple_request_action(gc, _("Verify Public Key"), tmp, tmp2,
-						PURPLE_DEFAULT_ACTION_NONE,
-						purple_connection_get_account(gc), entity, NULL, verify, 3,
-			    _("Yes"), G_CALLBACK(silcpurple_verify_cb),
-			    _("No"), G_CALLBACK(silcpurple_verify_cb),
-			    _("_View..."), G_CALLBACK(silcpurple_verify_details));
+			      PURPLE_DEFAULT_ACTION_NONE,
+			      purple_connection_get_account(gc), entity, NULL, verify, 3,
+			      _("Yes"), G_CALLBACK(silcpurple_verify_cb),
+			      _("No"), G_CALLBACK(silcpurple_verify_cb),
+			      _("_View..."), G_CALLBACK(silcpurple_verify_details));
 }
 
 void silcpurple_verify_public_key(SilcClient client, SilcClientConnection conn,
-				const char *name, SilcSocketType conn_type,
-				unsigned char *pk, SilcUInt32 pk_len,
-				SilcSKEPKType pk_type,
-				SilcVerifyPublicKey completion, void *context)
+				  const char *name, SilcConnectionType conn_type,
+				  SilcPublicKey public_key,
+				  SilcVerifyPublicKey completion, void *context)
 {
 	PurpleConnection *gc = client->application;
 	int i;
@@ -133,14 +126,18 @@
 	char *fingerprint, *babbleprint;
 	struct passwd *pw;
 	struct stat st;
-	char *entity = ((conn_type == SILC_SOCKET_TYPE_SERVER ||
-			 conn_type == SILC_SOCKET_TYPE_ROUTER) ?
+	char *entity = ((conn_type == SILC_CONN_SERVER ||
+			 conn_type == SILC_CONN_ROUTER) ?
 			"server" : "client");
 	PublicKeyVerify verify;
+	const char *ip, *hostname;
+	SilcUInt16 port;
+	unsigned char *pk;
+	SilcUInt32 pk_len;
 
-	if (pk_type != SILC_SKE_PK_TYPE_SILC) {
+	if (silc_pkcs_get_type(public_key) != SILC_PKCS_SILC) {
 		purple_notify_error(gc, _("Verify Public Key"),
-				  _("Unsupported public key type"), NULL);
+				    _("Unsupported public key type"), NULL);
 		if (completion)
 			completion(FALSE, context);
 		return;
@@ -157,17 +154,22 @@
 	memset(filename2, 0, sizeof(filename2));
 	memset(file, 0, sizeof(file));
 
-	if (conn_type == SILC_SOCKET_TYPE_SERVER ||
-	    conn_type == SILC_SOCKET_TYPE_ROUTER) {
+	silc_socket_stream_get_info(silc_packet_stream_get_stream(conn->stream),
+				    NULL, &hostname, &ip, &port);
+
+	pk = silc_pkcs_public_key_encode(public_key, &pk_len);
+
+	if (conn_type == SILC_CONN_SERVER ||
+	    conn_type == SILC_CONN_ROUTER) {
 		if (!name) {
 			g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
-				   conn->sock->ip, conn->sock->port);
+				   ip, port);
 			g_snprintf(filename, sizeof(filename) - 1,
 				   "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s",
 				   silcpurple_silcdir(), entity, file);
 
 			g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
-				   conn->sock->hostname, conn->sock->port);
+				   hostname, port);
 			g_snprintf(filename2, sizeof(filename2) - 1,
 				   "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s",
 				   silcpurple_silcdir(), entity, file);
@@ -176,7 +178,7 @@
 			hostf = filename2;
 		} else {
 			g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
-				   name, conn->sock->port);
+				   name, port);
 			g_snprintf(filename, sizeof(filename) - 1,
 				   "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s",
 				   silcpurple_silcdir(), entity, file);
@@ -206,12 +208,10 @@
 	verify->conn = conn;
 	verify->filename = strdup(ipf);
 	verify->entity = strdup(entity);
-	verify->entity_name = (conn_type != SILC_SOCKET_TYPE_CLIENT ?
-			       (name ? strdup(name) : strdup(conn->sock->hostname))
+	verify->entity_name = (conn_type != SILC_CONN_CLIENT ?
+			       (name ? strdup(name) : strdup(hostname))
 			       : NULL);
-	verify->pk = silc_memdup(pk, pk_len);
-	verify->pk_len = pk_len;
-	verify->pk_type = pk_type;
+	verify->public_key = silc_pkcs_public_key_copy(public_key);
 	verify->completion = completion;
 	verify->context = context;
 	fingerprint = verify->fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
@@ -221,7 +221,7 @@
 	if (g_stat(ipf, &st) < 0 && (!hostf || g_stat(hostf, &st) < 0)) {
 		/* Key does not exist, ask user to verify the key and save it */
 		silcpurple_verify_ask(name ? name : entity,
-				    fingerprint, babbleprint, verify);
+				      fingerprint, babbleprint, verify);
 		return;
 	} else {
 		/* The key already exists, verify it. */
@@ -230,14 +230,8 @@
 		SilcUInt32 encpk_len;
 
 		/* Load the key file, try for both IP filename and hostname filename */
-		if (!silc_pkcs_load_public_key(ipf, &public_key,
-					       SILC_PKCS_FILE_PEM) &&
-		    !silc_pkcs_load_public_key(ipf, &public_key,
-					       SILC_PKCS_FILE_BIN) &&
-		    (!hostf || (!silc_pkcs_load_public_key(hostf, &public_key,
-							   SILC_PKCS_FILE_PEM) &&
-				!silc_pkcs_load_public_key(hostf, &public_key,
-							   SILC_PKCS_FILE_BIN)))) {
+		if (!silc_pkcs_load_public_key(ipf, &public_key) &&
+		    (!hostf || (!silc_pkcs_load_public_key(hostf, &public_key)))) {
 			silcpurple_verify_ask(name ? name : entity,
 					    fingerprint, babbleprint, verify);
 			return;
@@ -266,9 +260,9 @@
 		silc_free(verify->filename);
 		silc_free(verify->entity);
 		silc_free(verify->entity_name);
-		silc_free(verify->pk);
 		silc_free(verify->fingerprint);
 		silc_free(verify->babbleprint);
+		silc_pkcs_public_key_free(verify->public_key);
 		silc_free(verify);
 	}
 }
--- a/libpurple/protocols/silc/silc.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/silc/silc.c	Mon Jun 18 01:48:35 2007 +0000
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2004 - 2005 Pekka Riikonen
+  Copyright (C) 2004 - 2007 Pekka Riikonen
 
   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
@@ -17,7 +17,7 @@
 
 */
 
-#include "silcincludes.h"
+#include "silc.h"
 #include "silcclient.h"
 #include "silcpurple.h"
 #include "version.h"
@@ -26,6 +26,15 @@
 extern SilcClientOperations ops;
 static PurplePlugin *silc_plugin = NULL;
 
+/* Error log message callback */
+
+static SilcBool silcpurple_log_error(SilcLogType type, char *message,
+				     void *context)
+{
+	silc_say(NULL, NULL, SILC_CLIENT_MESSAGE_ERROR, message);
+	return TRUE;
+}
+
 static const char *
 silcpurple_list_icon(PurpleAccount *a, PurpleBuddy *b)
 {
@@ -102,8 +111,8 @@
 	idp = silc_id_payload_encode(sg->conn->local_id, SILC_ID_CLIENT);
 	SILC_PUT32_MSB(mode, mb);
 	silc_client_command_send(sg->client, sg->conn, SILC_COMMAND_UMODE,
-				 ++sg->conn->cmd_ident, 2,
-				 1, idp->data, idp->len,
+				 silcpurple_command_reply, NULL, 2,
+				 1, idp->data, silc_buffer_len(idp),
 				 2, mb, sizeof(mb));
 	silc_buffer_free(idp);
 }
@@ -115,91 +124,54 @@
 silcpurple_keepalive(PurpleConnection *gc)
 {
 	SilcPurple sg = gc->proto_data;
-	silc_client_send_packet(sg->client, sg->conn, SILC_PACKET_HEARTBEAT,
-				NULL, 0);
+	silc_packet_send(sg->conn->stream, SILC_PACKET_HEARTBEAT, 0,
+			 NULL, 0);
 }
 
-static int
+static gboolean
 silcpurple_scheduler(gpointer *context)
 {
-	SilcPurple sg = (SilcPurple)context;
-	silc_client_run_one(sg->client);
-	return 1;
+	SilcClient client = (SilcClient)context;
+	silc_client_run_one(client);
+	return TRUE;
 }
 
 static void
-silcpurple_nickname_parse(const char *nickname,
-			char **ret_nickname)
-{
-	silc_parse_userfqdn(nickname, ret_nickname, NULL);
-}
-
-static void
-silcpurple_login_connected(gpointer data, gint source, const gchar *error_message)
+silcpurple_connect_cb(SilcClient client, SilcClientConnection conn,
+		      SilcClientConnectionStatus status, SilcStatus error,
+		      const char *message, void *context)
 {
-	PurpleConnection *gc = data;
+	PurpleConnection *gc = context;
 	SilcPurple sg;
-	SilcClient client;
-	SilcClientConnection conn;
-	PurpleAccount *account;
-	SilcClientConnectionParams params;
-	const char *dfile;
-
-	g_return_if_fail(gc != NULL);
+	SilcUInt32 mask;
+	char tz[16];
+	PurpleStoredImage *img;
+#ifdef HAVE_SYS_UTSNAME_H
+	struct utsname u;
+#endif
 
 	sg = gc->proto_data;
 
-	if (source < 0) {
-		purple_connection_error(gc, _("Connection failed"));
-		return;
-	}
+	switch (status) {
+	case SILC_CLIENT_CONN_SUCCESS:
+	case SILC_CLIENT_CONN_SUCCESS_RESUME:
+		sg->conn = conn;
 
-	client = sg->client;
-	account = sg->account;
-
-	/* Get session detachment data, if available */
-	memset(&params, 0, sizeof(params));
-	dfile = silcpurple_session_file(purple_account_get_username(sg->account));
-	params.detach_data = (unsigned char *)silc_file_readfile(dfile, &params.detach_data_len);
-	if (params.detach_data)
-		params.detach_data[params.detach_data_len] = 0;
+		/* Connection created successfully */
+		purple_connection_set_state(gc, PURPLE_CONNECTED);
 
-	/* Add connection to SILC client library */
-	conn = silc_client_add_connection(
-			  sg->client, &params,
-			  (char *)purple_account_get_string(account, "server",
-							  "silc.silcnet.org"),
-			  purple_account_get_int(account, "port", 706), sg);
-	if (!conn) {
-		purple_connection_error(gc, _("Cannot initialize SILC Client connection"));
-		gc->proto_data = NULL;
-		return;
-	}
-	sg->conn = conn;
+		/* Send the server our buddy list */
+		silcpurple_send_buddylist(gc);
+
+		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
 
-	/* Progress */
-	if (params.detach_data) {
-		purple_connection_update_progress(gc, _("Resuming session"), 2, 5);
-		sg->resuming = TRUE;
-	} else {
-		purple_connection_update_progress(gc, _("Performing key exchange"), 2, 5);
-	}
-
-	/* Perform SILC Key Exchange.  The "silc_connected" will be called
-	   eventually. */
-	silc_client_start_key_exchange(sg->client, sg->conn, source);
+		/* Send any UMODEs configured for account */
+		if (purple_account_get_bool(sg->account, "block-ims", FALSE)) {
+			silc_client_command_call(sg->client, sg->conn, NULL,
+						 "UMODE", "+P", NULL);
+		}
 
-	/* Set default attributes */
-	if (!purple_account_get_bool(account, "reject-attrs", FALSE)) {
-		SilcUInt32 mask;
-		const char *tmp;
-#ifdef SILC_ATTRIBUTE_USER_ICON
-		PurpleStoredImage *img;
-#endif
-#ifdef HAVE_SYS_UTSNAME_H
-		struct utsname u;
-#endif
-
+		/* Set default attributes */
 		mask = SILC_ATTRIBUTE_MOOD_NORMAL;
 		silc_client_attribute_add(client, conn,
 					  SILC_ATTRIBUTE_STATUS_MOOD,
@@ -222,36 +194,191 @@
 						  (void *)&dev, sizeof(dev));
 		}
 #endif
-#ifdef _WIN32
-		tmp = _tzname[0];
-#else
-		tmp = tzname[0];
-#endif
+		silc_timezone(tz, sizeof(tz));
 		silc_client_attribute_add(client, conn,
 					  SILC_ATTRIBUTE_TIMEZONE,
-					  (void *)tmp, strlen(tmp));
+					  (void *)tz, strlen(tz));
 
-#ifdef SILC_ATTRIBUTE_USER_ICON
 		/* Set our buddy icon */
-		img = purple_buddy_icons_find_account_icon(account);
+		img = purple_buddy_icons_find_account_icon(sg->account);
 		silcpurple_buddy_set_icon(gc, img);
 		purple_imgstore_unref(img);
-#endif
+
+		return;
+		break;
+
+	case SILC_CLIENT_CONN_DISCONNECTED:
+		/* Disconnected */
+		if (sg->resuming && !sg->detaching)
+		  g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
+
+		/* Close the connection */
+		if (!sg->detaching)
+		  purple_connection_error(gc, _("Disconnected by server"));
+		else
+		  /* TODO: Does this work correctly? Maybe we need to set wants_to_die? */
+		  purple_account_disconnect(purple_connection_get_account(gc));
+		break;
+
+	case SILC_CLIENT_CONN_ERROR:
+		purple_connection_error(gc, _("Error during connecting to SILC Server"));
+		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
+		break;
+
+	case SILC_CLIENT_CONN_ERROR_KE:
+		purple_connection_error(gc, _("Key Exchange failed"));
+		break;
+
+	case SILC_CLIENT_CONN_ERROR_AUTH:
+		purple_connection_error(gc, _("Authentication failed"));
+		break;
+
+	case SILC_CLIENT_CONN_ERROR_RESUME:
+		purple_connection_error(gc,
+				      _("Resuming detached session failed. "
+					"Press Reconnect to create new connection."));
+		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
+		break;
+
+	case SILC_CLIENT_CONN_ERROR_TIMEOUT:
+		purple_connection_error(gc, _("Connection Timeout"));
+		break;
 	}
 
+	/* Error */
+	sg->conn = NULL;
+}
+
+static void
+silcpurple_stream_created(SilcSocketStreamStatus status, SilcStream stream,
+			  void *context)
+{
+	PurpleConnection *gc = context;
+	SilcPurple sg;
+	SilcClient client;
+	SilcClientConnectionParams params;
+	const char *dfile;
+
+	sg = gc->proto_data;
+
+	if (status != SILC_SOCKET_OK) {
+		purple_connection_error(gc, _("Connection failed"));
+		silc_pkcs_public_key_free(sg->public_key);
+		silc_pkcs_private_key_free(sg->private_key);
+		silc_free(sg);
+		gc->proto_data = NULL;
+		return;
+	}
+
+	client = sg->client;
+
+	/* Progress */
+	if (params.detach_data) {
+		purple_connection_update_progress(gc, _("Resuming session"), 2, 5);
+		sg->resuming = TRUE;
+	} else {
+		purple_connection_update_progress(gc, _("Performing key exchange"), 2, 5);
+	}
+
+	/* Get session detachment data, if available */
+	memset(&params, 0, sizeof(params));
+	dfile = silcpurple_session_file(purple_account_get_username(sg->account));
+	params.detach_data = (unsigned char *)silc_file_readfile(dfile, &params.detach_data_len);
+	if (params.detach_data)
+		params.detach_data[params.detach_data_len] = 0;
+	params.ignore_requested_attributes = FALSE;
+	params.pfs = purple_account_get_bool(sg->account, "pfs", FALSE);
+
+	/* Perform SILC Key Exchange. */
+	silc_client_key_exchange(sg->client, &params, sg->public_key,
+				 sg->private_key, stream, SILC_CONN_SERVER,
+				 silcpurple_connect_cb, gc);
+
 	silc_free(params.detach_data);
 }
 
 static void
+silcpurple_login_connected(gpointer data, gint source, const gchar *error_message)
+{
+	PurpleConnection *gc = data;
+	SilcPurple sg;
+
+	g_return_if_fail(gc != NULL);
+
+	sg = gc->proto_data;
+
+	if (source < 0) {
+		purple_connection_error(gc, _("Connection failed"));
+		silc_pkcs_public_key_free(sg->public_key);
+		silc_pkcs_private_key_free(sg->private_key);
+		silc_free(sg);
+		gc->proto_data = NULL;
+		return;
+	}
+
+	/* Wrap socket to TCP stream */
+	silc_socket_tcp_stream_create(source, TRUE, FALSE,
+				      sg->client->schedule,
+				      silcpurple_stream_created, gc);
+}
+
+static void silcpurple_running(SilcClient client, void *context)
+{
+	PurpleAccount *account = context;
+	PurpleConnection *gc = account->gc;
+	SilcPurple sg;
+	char pkd[256], prd[256];
+
+	sg = silc_calloc(1, sizeof(*sg));
+	if (!sg)
+		return;
+	memset(sg, 0, sizeof(*sg));
+	sg->client = client;
+	sg->gc = gc;
+	sg->account = account;
+	sg->scheduler = SILC_PTR_TO_32(gc->proto_data);
+	gc->proto_data = sg;
+
+	/* Progress */
+	purple_connection_update_progress(gc, _("Connecting to SILC Server"), 1, 5);
+
+	/* Load SILC key pair */
+	g_snprintf(pkd, sizeof(pkd), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir());
+	g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir());
+	if (!silc_load_key_pair((char *)purple_account_get_string(account, "public-key", pkd),
+				(char *)purple_account_get_string(account, "private-key", prd),
+				(gc->password == NULL) ? "" : gc->password,
+				&sg->public_key, &sg->private_key)) {
+		g_snprintf(pkd, sizeof(pkd), _("Could not load SILC key pair"));
+		purple_connection_error(gc, pkd);
+		gc->proto_data = NULL;
+		silc_free(sg);
+		return;
+	}
+
+	/* Connect to the SILC server */
+	if (purple_proxy_connect(gc, account,
+				 purple_account_get_string(account, "server",
+							   "silc.silcnet.org"),
+				 purple_account_get_int(account, "port", 706),
+				 silcpurple_login_connected, gc) == NULL)
+	{
+		purple_connection_error(gc, _("Unable to create connection"));
+		gc->proto_data = NULL;
+		silc_free(sg);
+		return;
+	}
+}
+
+static void
 silcpurple_login(PurpleAccount *account)
 {
-	SilcPurple sg;
 	SilcClient client;
-	SilcClientParams params;
 	PurpleConnection *gc;
-	char pkd[256], prd[256];
+	SilcClientParams params;
 	const char *cipher, *hmac;
-	char *realname;
+	char *username, *hostname, *realname, **up;
+	guint scheduler;
 	int i;
 
 	gc = account->gc;
@@ -260,10 +387,7 @@
 	gc->proto_data = NULL;
 
 	memset(&params, 0, sizeof(params));
-	strcat(params.nickname_format, "%n@%h%a");
-	params.nickname_parse = silcpurple_nickname_parse;
-	params.ignore_requested_attributes =
-		purple_account_get_bool(account, "reject-attrs", FALSE);
+	strcat(params.nickname_format, "%n#a");
 
 	/* Allocate SILC client */
 	client = silc_client_alloc(&ops, &params, gc, NULL);
@@ -273,32 +397,28 @@
 	}
 
 	/* Get username, real name and local hostname for SILC library */
-	if (purple_account_get_username(account)) {
-		const char *u = purple_account_get_username(account);
-		char **up = g_strsplit(u, "@", 2);
-		client->username = strdup(up[0]);
-		g_strfreev(up);
-	} else {
-		client->username = silc_get_username();
-		purple_account_set_username(account, client->username);
+	if (!purple_account_get_username(account))
+		purple_account_set_username(account, silc_get_username());
+
+	username = (char *)purple_account_get_username(account);
+	up = g_strsplit(username, "@", 2);
+	username = strdup(up[0]);
+	g_strfreev(up);
+
+	if (!purple_account_get_user_info(account)) {
+		purple_account_set_user_info(account, silc_get_real_name());
+		if (!purple_account_get_user_info(account))
+			purple_account_set_user_info(account,
+						     "John T. Noname");
 	}
-	realname = silc_get_real_name();
-	if (purple_account_get_user_info(account)) {
-		client->realname = strdup(purple_account_get_user_info(account));
-		free(realname);
-	} else if ((silc_get_real_name() != NULL) && (*realname != '\0')) {
-		client->realname = realname;
-		purple_account_set_user_info(account, client->realname);
-	} else {
-		free(realname);
-		client->realname = strdup(_("John Noname"));
-	}
-	client->hostname = silc_net_localhost();
+	realname = (char *)purple_account_get_user_info(account);
+	hostname = silc_net_localhost();
 
-	purple_connection_set_display_name(gc, client->username);
+	purple_connection_set_display_name(gc, username);
 
 	/* Register requested cipher and HMAC */
-	cipher = purple_account_get_string(account, "cipher", SILC_DEFAULT_CIPHER);
+	cipher = purple_account_get_string(account, "cipher",
+					   SILC_DEFAULT_CIPHER);
 	for (i = 0; silc_default_ciphers[i].name; i++)
 		if (!strcmp(silc_default_ciphers[i].name, cipher)) {
 			silc_cipher_register(&(silc_default_ciphers[i]));
@@ -312,7 +432,8 @@
 		}
 
 	/* Init SILC client */
-	if (!silc_client_init(client)) {
+	if (!silc_client_init(client, username, hostname, realname,
+			      silcpurple_running, account)) {
 		gc->wants_to_die = TRUE;
 		purple_connection_error(gc, _("Cannot initialize SILC protocol"));
 		return;
@@ -321,63 +442,23 @@
 	/* Check the ~/.silc dir and create it, and new key pair if necessary. */
 	if (!silcpurple_check_silc_dir(gc)) {
 		gc->wants_to_die = TRUE;
-		purple_connection_error(gc, _("Cannot find/access ~/.silc directory"));
-		return;
-	}
-
-	/* Progress */
-	purple_connection_update_progress(gc, _("Connecting to SILC Server"), 1, 5);
-
-	/* Load SILC key pair */
-	g_snprintf(pkd, sizeof(pkd), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir());
-	g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir());
-	if (!silc_load_key_pair((char *)purple_account_get_string(account, "public-key", pkd),
-							(char *)purple_account_get_string(account, "private-key", prd),
-				(gc->password == NULL) ? "" : gc->password, &client->pkcs,
-				&client->public_key, &client->private_key)) {
-		g_snprintf(pkd, sizeof(pkd), _("Could not load SILC key pair: %s"), strerror(errno));
-		purple_connection_error(gc, pkd);
-		return;
-	}
-
-	sg = silc_calloc(1, sizeof(*sg));
-	if (!sg)
-		return;
-	memset(sg, 0, sizeof(*sg));
-	sg->client = client;
-	sg->gc = gc;
-	sg->account = account;
-	gc->proto_data = sg;
-
-	/* Connect to the SILC server */
-	if (purple_proxy_connect(gc, account,
-			       purple_account_get_string(account, "server",
-						       "silc.silcnet.org"),
-			       purple_account_get_int(account, "port", 706),
-			       silcpurple_login_connected, gc) == NULL)
-	{
-		purple_connection_error(gc, _("Unable to create connection"));
+		purple_connection_error(gc, _("Error loading SILC key pair"));
 		return;
 	}
 
 	/* Schedule SILC using Glib's event loop */
-#ifndef _WIN32
-	sg->scheduler = g_timeout_add(5, (GSourceFunc)silcpurple_scheduler, sg);
-#else
-	sg->scheduler = g_timeout_add(300, (GSourceFunc)silcpurple_scheduler, sg);
-#endif
+	scheduler = purple_timeout_add(300, (GSourceFunc)silcpurple_scheduler, client);
+	gc->proto_data = SILC_32_TO_PTR(scheduler);
 }
 
 static int
 silcpurple_close_final(gpointer *context)
 {
 	SilcPurple sg = (SilcPurple)context;
-	silc_client_stop(sg->client);
+	silc_client_stop(sg->client, NULL, NULL);
 	silc_client_free(sg->client);
-#ifdef HAVE_SILCMIME_H
 	if (sg->mimeass)
 		silc_mime_assembler_free(sg->mimeass);
-#endif
 	silc_free(sg);
 	return 0;
 }
@@ -391,13 +472,13 @@
 
 	/* Send QUIT */
 	silc_client_command_call(sg->client, sg->conn, NULL,
-				 "QUIT", "Download Purple: " PURPLE_WEBSITE, NULL);
+				 "QUIT", "Download Pidgin: " PURPLE_WEBSITE, NULL);
 
 	if (sg->conn)
 		silc_client_close_connection(sg->client, sg->conn);
 
-	g_source_remove(sg->scheduler);
-	g_timeout_add(1, (GSourceFunc)silcpurple_close_final, sg);
+	purple_timeout_remove(sg->scheduler);
+	purple_timeout_add(1, (GSourceFunc)silcpurple_close_final, sg);
 }
 
 
@@ -599,7 +680,7 @@
 	gboolean cemail = FALSE, ccall = FALSE, csms = FALSE,
 		cmms = FALSE, cchat = TRUE, cvideo = FALSE;
 	gboolean device = TRUE;
-	char status[1024];
+	char status[1024], tz[16];
 
 	sg = gc->proto_data;
 	if (!sg)
@@ -726,11 +807,9 @@
 					  purple_account_get_string(sg->account, "vcard", ""),
 					  FALSE);
 	purple_request_field_group_add_field(g, f);
-#ifdef _WIN32
-	f = purple_request_field_string_new("timezone", _("Timezone"), _tzname[0], FALSE);
-#else
-	f = purple_request_field_string_new("timezone", _("Timezone"), tzname[0], FALSE);
-#endif
+
+	silc_timezone(tz, sizeof(tz));
+	f = purple_request_field_string_new("timezone", _("Timezone (UTC)"), tz, FALSE);
 	purple_request_field_group_add_field(g, f);
 	purple_request_fields_add_group(fields, g);
 
@@ -865,12 +944,14 @@
 	if (f)
 		c = purple_request_field_string_get_value(f);
 
-	identifier = silc_pkcs_encode_identifier((char *)un, (char *)hn,
-						 (char *)rn, (char *)e, (char *)o, (char *)c);
+	identifier = silc_pkcs_silc_encode_identifier((char *)un, (char *)hn,
+						      (char *)rn, (char *)e,
+						      (char *)o, (char *)c,
+						      NULL);
 
 	/* Create the key pair */
 	if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS, keylen, pkfile, prfile,
-				  identifier, pass1, NULL, &public_key, NULL,
+				  identifier, pass1, &public_key, NULL,
 				  FALSE)) {
 		purple_notify_error(
 		     gc, _("Create New SILC Key Pair"), _("Key Pair Generation failed"), NULL);
@@ -945,10 +1026,10 @@
 	purple_request_fields_add_group(fields, g);
 
 	purple_request_fields(gc, _("Create New SILC Key Pair"),
-			    _("Create New SILC Key Pair"), NULL, fields,
-			    _("Generate Key Pair"), G_CALLBACK(silcpurple_create_keypair_cb),
-			    _("Cancel"), G_CALLBACK(silcpurple_create_keypair_cancel),
-				gc->account, NULL, NULL, gc);
+			      _("Create New SILC Key Pair"), NULL, fields,
+			      _("Generate Key Pair"), G_CALLBACK(silcpurple_create_keypair_cb),
+			      _("Cancel"), G_CALLBACK(silcpurple_create_keypair_cancel),
+			      gc->account, NULL, NULL, gc);
 
 	g_strfreev(u);
 	silc_free(hostname);
@@ -967,8 +1048,8 @@
         char prd[256];
 	g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.pub", silcpurple_silcdir());
 	silc_change_private_key_passphrase(purple_account_get_string(gc->account,
-								   "private-key",
-								   prd), old, new);
+								     "private-key",
+								     prd), old, new);
 }
 
 static void
@@ -986,15 +1067,12 @@
 static GList *
 silcpurple_actions(PurplePlugin *plugin, gpointer context)
 {
-	PurpleConnection *gc = context;
 	GList *list = NULL;
 	PurplePluginAction *act;
 
-	if (!purple_account_get_bool(gc->account, "reject-attrs", FALSE)) {
-		act = purple_plugin_action_new(_("Online Status"),
-				silcpurple_attrs);
-		list = g_list_append(list, act);
-	}
+	act = purple_plugin_action_new(_("Online Status"),
+			silcpurple_attrs);
+	list = g_list_append(list, act);
 
 	act = purple_plugin_action_new(_("Detach From Server"),
 			silcpurple_detach);
@@ -1032,49 +1110,43 @@
 
 static void
 silcpurple_send_im_resolved(SilcClient client,
-			  SilcClientConnection conn,
-			  SilcClientEntry *clients,
-			  SilcUInt32 clients_count,
-			  void *context)
+			    SilcClientConnection conn,
+			    SilcStatus status,
+			    SilcDList clients,
+			    void *context)
 {
 	PurpleConnection *gc = client->application;
 	SilcPurple sg = gc->proto_data;
 	SilcPurpleIM im = context;
 	PurpleConversation *convo;
-	char tmp[256], *nickname = NULL;
+	char tmp[256];
 	SilcClientEntry client_entry;
-#ifdef HAVE_SILCMIME_H
 	SilcDList list;
-#endif
 
 	convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, im->nick,
-							sg->account);
+						      sg->account);
 	if (!convo)
 		return;
 
 	if (!clients)
 		goto err;
 
-	if (clients_count > 1) {
-		silc_parse_userfqdn(im->nick, &nickname, NULL);
-
+	if (silc_dlist_count(clients) > 1) {
 		/* Find the correct one. The im->nick might be a formatted nick
 		   so this will find the correct one. */
 		clients = silc_client_get_clients_local(client, conn,
-							nickname, im->nick,
-							&clients_count);
+							im->nick, FALSE);
 		if (!clients)
 			goto err;
-		client_entry = clients[0];
-		silc_free(clients);
-	} else {
-		client_entry = clients[0];
 	}
 
-#ifdef HAVE_SILCMIME_H
+	silc_dlist_start(clients);
+	client_entry = silc_dlist_get(clients);
+
 	/* Check for images */
 	if (im->gflags & PURPLE_MESSAGE_IMAGES) {
-		list = silcpurple_image_message(im->message, (SilcUInt32 *)&im->flags);
+		list = silcpurple_image_message(im->message,
+						(SilcUInt32 *)(void *)&im->flags);
 		if (list) {
 			/* Send one or more MIME message.  If more than one, they
 			   are MIME fragments due to over large message */
@@ -1083,22 +1155,21 @@
 			silc_dlist_start(list);
 			while ((buf = silc_dlist_get(list)) != SILC_LIST_END)
 				silc_client_send_private_message(client, conn,
-								 client_entry, im->flags,
-								 buf->data, buf->len,
-								 TRUE);
+								 client_entry, im->flags, NULL,
+								 buf->data,
+								 silc_buffer_len(buf));
 			silc_mime_partial_free(list);
 			purple_conv_im_write(PURPLE_CONV_IM(convo), conn->local_entry->nickname,
-				   im->message, 0, time(NULL));
+					     im->message, 0, time(NULL));
 			goto out;
 		}
 	}
-#endif
 
 	/* Send the message */
 	silc_client_send_private_message(client, conn, client_entry, im->flags,
-					 (unsigned char *)im->message, im->message_len, TRUE);
+					 NULL, (unsigned char *)im->message, im->message_len);
 	purple_conv_im_write(PURPLE_CONV_IM(convo), conn->local_entry->nickname,
-			   im->message, 0, time(NULL));
+			     im->message, 0, time(NULL));
 	goto out;
 
  err:
@@ -1110,24 +1181,22 @@
 	g_free(im->nick);
 	g_free(im->message);
 	silc_free(im);
-	silc_free(nickname);
 }
 
 static int
 silcpurple_send_im(PurpleConnection *gc, const char *who, const char *message,
-		 PurpleMessageFlags flags)
+		   PurpleMessageFlags flags)
 {
 	SilcPurple sg = gc->proto_data;
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
-	SilcClientEntry *clients;
-	SilcUInt32 clients_count, mflags;
-	char *nickname, *msg, *tmp;
+	SilcDList clients;
+	SilcClientEntry client_entry;
+	SilcUInt32 mflags;
+	char *msg, *tmp;
 	int ret = 0;
 	gboolean sign = purple_account_get_bool(sg->account, "sign-verify", FALSE);
-#ifdef HAVE_SILCMIME_H
 	SilcDList list;
-#endif
 
 	if (!who || !message)
 		return 0;
@@ -1145,14 +1214,9 @@
 		mflags |= SILC_MESSAGE_FLAG_ACTION;
 	} else if (strlen(msg) > 1 && msg[0] == '/') {
 		if (!silc_client_command_call(client, conn, msg + 1))
-			purple_notify_error(gc, _("Call Command"), _("Cannot call command"),
-					_("Unknown command"));
-		g_free(tmp);
-		return 0;
-	}
-
-
-	if (!silc_parse_userfqdn(who, &nickname, NULL)) {
+			purple_notify_error(gc, _("Call Command"),
+					    _("Cannot call command"),
+					    _("Unknown command"));
 		g_free(tmp);
 		return 0;
 	}
@@ -1161,8 +1225,7 @@
 		mflags |= SILC_MESSAGE_FLAG_SIGNED;
 
 	/* Find client entry */
-	clients = silc_client_get_clients_local(client, conn, nickname, who,
-						&clients_count);
+	clients = silc_client_get_clients_local(client, conn, who, FALSE);
 	if (!clients) {
 		/* Resolve unknown user */
 		SilcPurpleIM im = silc_calloc(1, sizeof(*im));
@@ -1175,14 +1238,15 @@
 		im->message_len = strlen(im->message);
 		im->flags = mflags;
 		im->gflags = flags;
-		silc_client_get_clients(client, conn, nickname, NULL,
+		silc_client_get_clients(client, conn, who, NULL,
 					silcpurple_send_im_resolved, im);
-		silc_free(nickname);
 		g_free(tmp);
 		return 0;
 	}
 
-#ifdef HAVE_SILCMIME_H
+	silc_dlist_start(clients);
+	client_entry = silc_dlist_get(clients);
+
 	/* Check for images */
 	if (flags & PURPLE_MESSAGE_IMAGES) {
 		list = silcpurple_image_message(message, &mflags);
@@ -1195,27 +1259,24 @@
 			while ((buf = silc_dlist_get(list)) != SILC_LIST_END)
 				ret =
 			 	silc_client_send_private_message(client, conn,
-								 clients[0], mflags,
-								 buf->data, buf->len,
-								 TRUE);
+								 client_entry, mflags, NULL,
+								 buf->data,
+								 silc_buffer_len(buf));
 			silc_mime_partial_free(list);
 			g_free(tmp);
-			silc_free(nickname);
-			silc_free(clients);
+			silc_client_list_free(client, conn, clients);
 			return ret;
 		}
 	}
-#endif
 
 	/* Send private message directly */
-	ret = silc_client_send_private_message(client, conn, clients[0],
-					       mflags,
+	ret = silc_client_send_private_message(client, conn, client_entry,
+					       mflags, NULL,
 					       (unsigned char *)msg,
-					       strlen(msg), TRUE);
+					       strlen(msg));
 
 	g_free(tmp);
-	silc_free(nickname);
-	silc_free(clients);
+	silc_client_list_free(client, conn, clients);
 	return ret;
 }
 
@@ -1223,7 +1284,6 @@
 static GList *silcpurple_blist_node_menu(PurpleBlistNode *node) {
 	/* split this single menu building function back into the two
 	   original: one for buddies and one for chats */
-
 	if(PURPLE_BLIST_NODE_IS_CHAT(node)) {
 		return silcpurple_chat_menu((PurpleChat *) node);
 	} else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) {
@@ -1552,7 +1612,7 @@
 		return PURPLE_CMD_RET_FAILED;
 
 	silc_client_command_call(sg->client, sg->conn, NULL,
-				 "QUIT", (args && args[0]) ? args[0] : "Download Purple: " PURPLE_WEBSITE, NULL);
+				 "QUIT", (args && args[0]) ? args[0] : "Download Pidgin: " PURPLE_WEBSITE, NULL);
 
 	return PURPLE_CMD_RET_OK;
 }
@@ -1726,82 +1786,69 @@
 
 static PurplePluginProtocolInfo prpl_info =
 {
-#ifdef HAVE_SILCMIME_H
 	OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME |
 	OPT_PROTO_PASSWORD_OPTIONAL | OPT_PROTO_IM_IMAGE,
-#else
-	OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME |
-	OPT_PROTO_PASSWORD_OPTIONAL,
-#endif
-	NULL,						/* user_splits */
-	NULL,						/* protocol_options */
-#ifdef SILC_ATTRIBUTE_USER_ICON
+	NULL,					/* user_splits */
+	NULL,					/* protocol_options */
 	{"jpeg,gif,png,bmp", 0, 0, 96, 96, 0, PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */
-#else
-	NO_BUDDY_ICONS,
-#endif
-	silcpurple_list_icon,			/* list_icon */
-	NULL,				/* list_emblems */
-	silcpurple_status_text,		/* status_text */
+	silcpurple_list_icon,	                /* list_icon */
+	NULL,					/* list_emblems */
+	silcpurple_status_text,			/* status_text */
 	silcpurple_tooltip_text,		/* tooltip_text */
-	silcpurple_away_states,		/* away_states */
-	silcpurple_blist_node_menu,	/* blist_node_menu */
+	silcpurple_away_states,			/* away_states */
+	silcpurple_blist_node_menu,		/* blist_node_menu */
 	silcpurple_chat_info,			/* chat_info */
-	silcpurple_chat_info_defaults,/* chat_info_defaults */
-	silcpurple_login,				/* login */
-	silcpurple_close,				/* close */
+	silcpurple_chat_info_defaults,	        /* chat_info_defaults */
+	silcpurple_login,			/* login */
+	silcpurple_close,			/* close */
 	silcpurple_send_im,			/* send_im */
 	silcpurple_set_info,			/* set_info */
-	NULL,						/* send_typing */
+	NULL,					/* send_typing */
 	silcpurple_get_info,			/* get_info */
-	silcpurple_set_status,		/* set_status */
+	silcpurple_set_status,			/* set_status */
 	silcpurple_idle_set,			/* set_idle */
 	silcpurple_change_passwd,		/* change_passwd */
 	silcpurple_add_buddy,			/* add_buddy */
-	NULL,						/* add_buddies */
+	NULL,					/* add_buddies */
 	silcpurple_remove_buddy,		/* remove_buddy */
-	NULL,						/* remove_buddies */
-	NULL,						/* add_permit */
-	NULL,						/* add_deny */
-	NULL,						/* rem_permit */
-	NULL,						/* rem_deny */
-	NULL,						/* set_permit_deny */
+	NULL,					/* remove_buddies */
+	NULL,					/* add_permit */
+	NULL,					/* add_deny */
+	NULL,					/* rem_permit */
+	NULL,					/* rem_deny */
+	NULL,					/* set_permit_deny */
 	silcpurple_chat_join,			/* join_chat */
-	NULL,						/* reject_chat */
+	NULL,					/* reject_chat */
 	silcpurple_get_chat_name,		/* get_chat_name */
-	silcpurple_chat_invite,		/* chat_invite */
-	silcpurple_chat_leave,		/* chat_leave */
-	NULL,						/* chat_whisper */
+	silcpurple_chat_invite,			/* chat_invite */
+	silcpurple_chat_leave,			/* chat_leave */
+	NULL,					/* chat_whisper */
 	silcpurple_chat_send,			/* chat_send */
 	silcpurple_keepalive,			/* keepalive */
-	NULL,						/* register_user */
-	NULL,						/* get_cb_info */
-	NULL,						/* get_cb_away */
-	NULL,						/* alias_buddy */
-	NULL,						/* group_buddy */
-	NULL,						/* rename_group */
-	NULL,						/* buddy_free */
-	NULL,						/* convo_closed */
-	NULL,						/* normalize */
-#ifdef SILC_ATTRIBUTE_USER_ICON
-	silcpurple_buddy_set_icon,			/* set_buddy_icon */
-#else
-	NULL,
-#endif
-	NULL,						/* remove_group */
-	NULL,						/* get_cb_real_name */
-	silcpurple_chat_set_topic,	/* set_chat_topic */
-	NULL,						/* find_blist_chat */
-	silcpurple_roomlist_get_list,	/* roomlist_get_list */
-	silcpurple_roomlist_cancel,	/* roomlist_cancel */
-	NULL,						/* roomlist_expand_category */
-	NULL,						/* can_receive_file */
+	NULL,					/* register_user */
+	NULL,					/* get_cb_info */
+	NULL,					/* get_cb_away */
+	NULL,					/* alias_buddy */
+	NULL,					/* group_buddy */
+	NULL,					/* rename_group */
+	NULL,					/* buddy_free */
+	NULL,					/* convo_closed */
+	NULL,					/* normalize */
+	silcpurple_buddy_set_icon,		/* set_buddy_icon */
+	NULL,					/* remove_group */
+	NULL,					/* get_cb_real_name */
+	silcpurple_chat_set_topic,		/* set_chat_topic */
+	NULL,					/* find_blist_chat */
+	silcpurple_roomlist_get_list,	        /* roomlist_get_list */
+	silcpurple_roomlist_cancel,		/* roomlist_cancel */
+	NULL,				        /* roomlist_expand_category */
+	NULL,					/* can_receive_file */
 	silcpurple_ftp_send_file,		/* send_file */
 	silcpurple_ftp_new_xfer,		/* new_xfer */
-	NULL,						/* offline_message */
+	NULL,					/* offline_message */
 	&silcpurple_wb_ops,			/* whiteboard_prpl_ops */
-	NULL,                       /* send_raw */
-	NULL,                       /* roomlist_room_serialize */
+	NULL,					/* send_raw */
+	NULL,				        /* roomlist_room_serialize */
 
 	/* padding */
 	NULL,
@@ -1815,29 +1862,29 @@
 	PURPLE_PLUGIN_MAGIC,
 	PURPLE_MAJOR_VERSION,
 	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_PROTOCOL,                             /**< type           */
-	NULL,                                             /**< ui_requirement */
-	0,                                                /**< flags          */
-	NULL,                                             /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,                            /**< priority       */
+	PURPLE_PLUGIN_PROTOCOL,			/**< type           */
+	NULL,					/**< ui_requirement */
+	0,					/**< flags          */
+	NULL,					/**< dependencies   */
+	PURPLE_PRIORITY_DEFAULT,		/**< priority       */
 
-	"prpl-silc",                                      /**< id             */
-	"SILC",                                           /**< name           */
-	"1.0",                                            /**< version        */
+	"prpl-silc",				/**< id             */
+	"SILC",					/**< name           */
+	"1.1",					/**< version        */
 	/**  summary        */
 	N_("SILC Protocol Plugin"),
 	/**  description    */
 	N_("Secure Internet Live Conferencing (SILC) Protocol"),
-	"Pekka Riikonen",                                 /**< author         */
-	"http://silcnet.org/",                            /**< homepage       */
+	"Pekka Riikonen",			/**< author         */
+	"http://silcnet.org/",			/**< homepage       */
 
-	NULL,                                             /**< load           */
-	NULL,                                             /**< unload         */
-	NULL,                                             /**< destroy        */
+	NULL,					/**< load           */
+	NULL,					/**< unload         */
+	NULL,					/**< destroy        */
 
-	NULL,                                             /**< ui_info        */
-	&prpl_info,                                       /**< extra_info     */
-	NULL,                                             /**< prefs_info     */
+	NULL,					/**< ui_info        */
+	&prpl_info,				/**< extra_info     */
+	NULL,					/**< prefs_info     */
 	silcpurple_actions,
 
 	/* padding */
@@ -1864,18 +1911,18 @@
 
 	/* Account options */
 	option = purple_account_option_string_new(_("Connect server"),
-						"server",
-						"silc.silcnet.org");
+						  "server",
+						  "silc.silcnet.org");
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 	option = purple_account_option_int_new(_("Port"), "port", 706);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 	g_snprintf(tmp, sizeof(tmp), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir());
 	option = purple_account_option_string_new(_("Public Key file"),
-						"public-key", tmp);
+						  "public-key", tmp);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 	g_snprintf(tmp, sizeof(tmp), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir());
 	option = purple_account_option_string_new(_("Private Key file"),
-						"private-key", tmp);
+						  "private-key", tmp);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 
 	for (i = 0; silc_default_ciphers[i].name; i++) {
@@ -1897,35 +1944,36 @@
 	option = purple_account_option_list_new(_("HMAC"), "hmac", list);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 
-	option = purple_account_option_bool_new(_("Public key authentication"),
-					      "pubkey-auth", FALSE);
+	option = purple_account_option_bool_new(_("Use Perfect Forward Secrecy"),
+						"pfs", FALSE);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-	option = purple_account_option_bool_new(_("Reject watching by other users"),
-					      "reject-watch", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-	option = purple_account_option_bool_new(_("Block invites"),
-					      "block-invites", FALSE);
+
+	option = purple_account_option_bool_new(_("Public key authentication"),
+						"pubkey-auth", FALSE);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 	option = purple_account_option_bool_new(_("Block IMs without Key Exchange"),
-					      "block-ims", FALSE);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-	option = purple_account_option_bool_new(_("Reject online status attribute requests"),
-					      "reject-attrs", FALSE);
+						"block-ims", FALSE);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 	option = purple_account_option_bool_new(_("Block messages to whiteboard"),
-					      "block-wb", FALSE);
+						"block-wb", FALSE);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 	option = purple_account_option_bool_new(_("Automatically open whiteboard"),
-					      "open-wb", FALSE);
+						"open-wb", FALSE);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 	option = purple_account_option_bool_new(_("Digitally sign and verify all messages"),
-					      "sign-verify", FALSE);
+						"sign-verify", FALSE);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 
 	purple_prefs_remove("/plugins/prpl/silc");
 
+	silc_log_set_callback(SILC_LOG_ERROR, silcpurple_log_error, NULL);
 	silcpurple_register_commands();
 
+#if 0
+silc_log_debug(TRUE);
+silc_log_set_debug_string("*client*");
+#endif
+
 #ifdef _WIN32
 	silc_net_win32_init();
 #endif
--- a/libpurple/protocols/silc/silcpurple.h	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/silc/silcpurple.h	Mon Jun 18 01:48:35 2007 +0000
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2004 Pekka Riikonen
+  Copyright (C) 2004 - 2007 Pekka Riikonen
 
   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
@@ -66,6 +66,8 @@
 typedef struct SilcPurpleStruct {
 	SilcClient client;
 	SilcClientConnection conn;
+	SilcPublicKey public_key;
+	SilcPrivateKey private_key;
 
 	guint scheduler;
 	PurpleConnection *gc;
@@ -75,9 +77,7 @@
 
 	char *motd;
 	PurpleRoomlist *roomlist;
-#ifdef HAVE_SILCMIME_H
 	SilcMimeAssembler mimeass;
-#endif
 	unsigned int detaching            : 1;
 	unsigned int resuming             : 1;
 	unsigned int roomlist_canceled    : 1;
@@ -85,27 +85,29 @@
 } *SilcPurple;
 
 
+void silc_say(SilcClient client, SilcClientConnection conn,
+	      SilcClientMessageType type, char *msg, ...);
+SilcBool silcpurple_command_reply(SilcClient client, SilcClientConnection conn,
+				  SilcCommand command, SilcStatus status,
+				  SilcStatus error, void *context, va_list ap);
 gboolean silcpurple_check_silc_dir(PurpleConnection *gc);
-void silcpurple_chat_join_done(SilcClient client,
-			     SilcClientConnection conn,
-			     SilcClientEntry *clients,
-			     SilcUInt32 clients_count,
-			     void *context);
 const char *silcpurple_silcdir(void);
 const char *silcpurple_session_file(const char *account);
 void silcpurple_verify_public_key(SilcClient client, SilcClientConnection conn,
-				const char *name, SilcSocketType conn_type,
-				unsigned char *pk, SilcUInt32 pk_len,
-				SilcSKEPKType pk_type,
-				SilcVerifyPublicKey completion, void *context);
+				  const char *name,
+				  SilcConnectionType conn_type,
+				  SilcPublicKey public_key,
+				  SilcVerifyPublicKey completion,
+				  void *context);
 GList *silcpurple_buddy_menu(PurpleBuddy *buddy);
 void silcpurple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group);
 void silcpurple_send_buddylist(PurpleConnection *gc);
 void silcpurple_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group);
 void silcpurple_buddy_keyagr_request(SilcClient client,
-				   SilcClientConnection conn,
-				   SilcClientEntry client_entry,
-				   const char *hostname, SilcUInt16 port);
+				     SilcClientConnection conn,
+				     SilcClientEntry client_entry,
+				     const char *hostname, SilcUInt16 port,
+				     SilcUInt16 protocol);
 void silcpurple_idle_set(PurpleConnection *gc, int idle);
 void silcpurple_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full);
 char *silcpurple_status_text(PurpleBuddy *b);
@@ -140,17 +142,13 @@
 PurpleRoomlist *silcpurple_roomlist_get_list(PurpleConnection *gc);
 void silcpurple_roomlist_cancel(PurpleRoomlist *list);
 void silcpurple_chat_chauth_show(SilcPurple sg, SilcChannelEntry channel,
-			       SilcBuffer channel_pubkeys);
+				 SilcDList channel_pubkeys);
 void silcpurple_parse_attrs(SilcDList attrs, char **moodstr, char **statusstr,
 					 char **contactstr, char **langstr, char **devicestr,
 					 char **tzstr, char **geostr);
-#ifdef SILC_ATTRIBUTE_USER_ICON
 void silcpurple_buddy_set_icon(PurpleConnection *gc, PurpleStoredImage *img);
-#endif
-#ifdef HAVE_SILCMIME_H
 char *silcpurple_file2mime(const char *filename);
 SilcDList silcpurple_image_message(const char *msg, SilcUInt32 *mflags);
-#endif
 
 #ifdef _WIN32
 typedef int uid_t;
--- a/libpurple/protocols/silc/util.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/silc/util.c	Mon Jun 18 01:48:35 2007 +0000
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2004 - 2005 Pekka Riikonen
+  Copyright (C) 2004 - 2007 Pekka Riikonen
 
   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
@@ -17,7 +17,7 @@
 
 */
 
-#include "silcincludes.h"
+#include "silc.h"
 #include "silcclient.h"
 #include "silcpurple.h"
 #include "imgstore.h"
@@ -206,22 +206,24 @@
 		if (errno == ENOENT) {
 			purple_connection_update_progress(gc, _("Creating SILC key pair..."), 1, 5);
 			if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS,
-					     SILCPURPLE_DEF_PKCS_LEN,
-					     file_public_key, file_private_key, NULL,
-					     (gc->password == NULL) ? "" : gc->password,
-						 NULL, NULL, NULL, FALSE)) {
-				purple_debug_error("silc", "Couldn't create key pair\n");
+						  SILCPURPLE_DEF_PKCS_LEN,
+						  file_public_key,
+						  file_private_key, NULL,
+						  (gc->password == NULL)
+						  ? "" : gc->password,
+						  NULL, NULL, FALSE)) {
+				purple_connection_error(gc, _("Cannot create SILC key pair\n"));
 				return FALSE;
 			}
 
 			if ((g_stat(file_public_key, &st)) == -1) {
 				purple_debug_error("silc", "Couldn't stat '%s' public key, error: %s\n",
-					file_public_key, strerror(errno));
+						   file_public_key, strerror(errno));
 				return FALSE;
 			}
 		} else {
 			purple_debug_error("silc", "Couldn't stat '%s' public key, error: %s\n",
-							 file_public_key, strerror(errno));
+					   file_public_key, strerror(errno));
 			return FALSE;
 		}
 	}
@@ -237,7 +239,7 @@
 	if ((fd = g_open(file_private_key, O_RDONLY, 0)) != -1) {
 		if ((fstat(fd, &st)) == -1) {
 			purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n",
-							 file_private_key, strerror(errno));
+					   file_private_key, strerror(errno));
 			close(fd);
 			return FALSE;
 		}
@@ -246,18 +248,20 @@
 		if (errno == ENOENT) {
 			purple_connection_update_progress(gc, _("Creating SILC key pair..."), 1, 5);
 			if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS,
-					     SILCPURPLE_DEF_PKCS_LEN,
-					     file_public_key, file_private_key, NULL,
-					     (gc->password == NULL) ? "" : gc->password,
-						 NULL, NULL, NULL, FALSE)) {
-				purple_debug_error("silc", "Couldn't create key pair\n");
+						  SILCPURPLE_DEF_PKCS_LEN,
+						  file_public_key,
+						  file_private_key, NULL,
+						  (gc->password == NULL)
+						  ? "" : gc->password,
+						  NULL, NULL, FALSE)) {
+				purple_connection_error(gc, _("Cannot create SILC key pair\n"));
 				return FALSE;
 			}
 
 			if ((fd = g_open(file_private_key, O_RDONLY, 0)) != -1) {
 				if ((fstat(fd, &st)) == -1) {
 					purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n",
-							 file_private_key, strerror(errno));
+							   file_private_key, strerror(errno));
 					close(fd);
 					return FALSE;
 				}
@@ -266,12 +270,12 @@
 			 * will set the permissions */
 			else if ((g_stat(file_private_key, &st)) == -1) {
 				purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n",
-					file_private_key, strerror(errno));
+						   file_private_key, strerror(errno));
 				return FALSE;
 			}
 		} else {
 			purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n",
-							 file_private_key, strerror(errno));
+					   file_private_key, strerror(errno));
 			return FALSE;
 		}
 	}
@@ -323,30 +327,29 @@
 #endif
 
 void silcpurple_show_public_key(SilcPurple sg,
-			      const char *name, SilcPublicKey public_key,
-			      GCallback callback, void *context)
+				const char *name, SilcPublicKey public_key,
+				GCallback callback, void *context)
 {
 	SilcPublicKeyIdentifier ident;
-	SilcPKCS pkcs;
+	SilcSILCPublicKey silc_pubkey;
 	char *fingerprint, *babbleprint;
 	unsigned char *pk;
 	SilcUInt32 pk_len, key_len = 0;
 	GString *s;
 	char *buf;
 
-	ident = silc_pkcs_decode_identifier(public_key->identifier);
-	if (!ident)
-		return;
+	/* We support showing only SILC public keys for now */
+	if (silc_pkcs_get_type(public_key) != SILC_PKCS_SILC)
+	  return;
+
+	silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key);
+	ident = &silc_pubkey->identifier;
+	key_len = silc_pkcs_public_key_get_len(public_key);
 
 	pk = silc_pkcs_public_key_encode(public_key, &pk_len);
 	fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
 	babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
 
-	if (silc_pkcs_alloc((unsigned char *)public_key->name, &pkcs)) {
-		key_len = silc_pkcs_public_key_set(pkcs, public_key);
-		silc_pkcs_free(pkcs);
-	}
-
 	s = g_string_new("");
 	if (ident->realname)
 		/* Hint for translators: Please check the tabulator width here and in
@@ -363,8 +366,10 @@
 		g_string_append_printf(s, _("Organization: \t%s\n"), ident->org);
 	if (ident->country)
 		g_string_append_printf(s, _("Country: \t%s\n"), ident->country);
-	g_string_append_printf(s, _("Algorithm: \t%s\n"), public_key->name);
+	g_string_append_printf(s, _("Algorithm: \t%s\n"), silc_pubkey->pkcs->name);
 	g_string_append_printf(s, _("Key Length: \t%d bits\n"), (int)key_len);
+	if (ident->version)
+	  g_string_append_printf(s, _("Version: \t%s\n"), ident->version);
 	g_string_append_printf(s, "\n");
 	g_string_append_printf(s, _("Public Key Fingerprint:\n%s\n\n"), fingerprint);
 	g_string_append_printf(s, _("Public Key Babbleprint:\n%s"), babbleprint);
@@ -372,15 +377,14 @@
 	buf = g_string_free(s, FALSE);
 
 	purple_request_action(sg->gc, _("Public Key Information"),
-			    _("Public Key Information"),
-			    buf, 0, purple_connection_get_account(sg->gc),
-				NULL, NULL, context, 1, _("Close"), callback);
+			      _("Public Key Information"),
+			      buf, 0, purple_connection_get_account(sg->gc),
+			      NULL, NULL, context, 1, _("Close"), callback);
 
 	g_free(buf);
 	silc_free(fingerprint);
 	silc_free(babbleprint);
 	silc_free(pk);
-	silc_pkcs_free_identifier(ident);
 }
 
 SilcAttributePayload
@@ -400,7 +404,7 @@
 }
 
 void silcpurple_get_umode_string(SilcUInt32 mode, char *buf,
-			       SilcUInt32 buf_size)
+				 SilcUInt32 buf_size)
 {
 	memset(buf, 0, buf_size);
 	if ((mode & SILC_UMODE_SERVER_OPERATOR) ||
@@ -435,7 +439,7 @@
 }
 
 void silcpurple_get_chmode_string(SilcUInt32 mode, char *buf,
-				SilcUInt32 buf_size)
+				  SilcUInt32 buf_size)
 {
 	memset(buf, 0, buf_size);
 	if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
@@ -482,8 +486,8 @@
 
 void
 silcpurple_parse_attrs(SilcDList attrs, char **moodstr, char **statusstr,
-					 char **contactstr, char **langstr, char **devicestr,
-					 char **tzstr, char **geostr)
+		       char **contactstr, char **langstr, char **devicestr,
+		       char **tzstr, char **geostr)
 {
 	SilcAttributePayload attr;
 	SilcAttributeMood mood = 0;
@@ -610,7 +614,6 @@
 				geo.accuracy ? geo.accuracy : "");
 }
 
-#ifdef HAVE_SILCMIME_H
 /* Returns MIME type of filetype */
 
 char *silcpurple_file2mime(const char *filename)
@@ -620,23 +623,23 @@
 	ct = strrchr(filename, '.');
 	if (!ct)
 		return NULL;
-	else if (!g_ascii_strcasecmp(".png", ct))
+	else if (!strcasecmp(".png", ct))
 		return strdup("image/png");
-	else if (!g_ascii_strcasecmp(".jpg", ct))
+	else if (!strcasecmp(".jpg", ct))
 		return strdup("image/jpeg");
-	else if (!g_ascii_strcasecmp(".jpeg", ct))
+	else if (!strcasecmp(".jpeg", ct))
 		return strdup("image/jpeg");
-	else if (!g_ascii_strcasecmp(".gif", ct))
+	else if (!strcasecmp(".gif", ct))
 		return strdup("image/gif");
-	else if (!g_ascii_strcasecmp(".tiff", ct))
+	else if (!strcasecmp(".tiff", ct))
 		return strdup("image/tiff");
-	
+
 	return NULL;
 }
 
-/* Checks if message has images, and assembles MIME message if it has. 
-   If only one image is present, creates simple MIME image message.  If 
-   there are multiple images and/or text with images multipart MIME 
+/* Checks if message has images, and assembles MIME message if it has.
+   If only one image is present, creates simple MIME image message.  If
+   there are multiple images and/or text with images multipart MIME
    message is created. */
 
 SilcDList silcpurple_image_message(const char *msg, SilcUInt32 *mflags)
@@ -666,8 +669,9 @@
 			tmp = g_strndup(last, start - last);
 			text = purple_unescape_html(tmp);
 			g_free(tmp);
+
 			/* Add text */
-			silc_mime_add_data(p, text, strlen(text));
+			silc_mime_add_data(p, (const unsigned char *)text, strlen(text));
 			g_free(text);
 
 			if (!parts)
@@ -720,7 +724,7 @@
 				    "text/plain; charset=utf-8");
 
 		/* Add text */
-		silc_mime_add_data(p, tmp, strlen(tmp));
+		silc_mime_add_data(p, (const unsigned char *)tmp, strlen(tmp));
 		g_free(tmp);
 
 		if (!parts)
@@ -742,7 +746,7 @@
 		silc_mime_add_field(mime, "MIME-Version", "1.0");
 		g_snprintf(b, sizeof(b), "b%4X%4X",
 			   (unsigned int)time(NULL),
-			   silc_dlist_count(parts)); 
+			   silc_dlist_count(parts));
 		silc_mime_set_multipart(mime, "mixed", b);
 		silc_dlist_start(parts);
 		while ((p = silc_dlist_get(parts)) != SILC_LIST_END)
@@ -767,5 +771,3 @@
 
 	return list;
 }
-
-#endif /* HAVE_SILCMIME_H */
--- a/libpurple/protocols/silc/wb.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/silc/wb.c	Mon Jun 18 01:48:35 2007 +0000
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2005 Pekka Riikonen
+  Copyright (C) 2005 - 2007 Pekka Riikonen
 
   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
@@ -17,7 +17,7 @@
 
 */
 
-#include "silcincludes.h"
+#include "silc.h"
 #include "silcclient.h"
 #include "silcpurple.h"
 #include "wb.h"
@@ -30,7 +30,7 @@
   2 bytes	height
   4 bytes	brush color
   2 bytes	brush size
-  n bytes	data 
+  n bytes	data
 
   Data:
 
@@ -204,7 +204,7 @@
 		silc_buffer_pull(&buf, 8);
 		x = dx;
 		y = dy;
-		while (buf.len > 0) {
+		while (silc_buffer_len(&buf) > 0) {
 			ret = silc_buffer_unformat(&buf,
 						   SILC_STR_UI_INT(&dx),
 						   SILC_STR_UI_INT(&dy),
@@ -214,7 +214,7 @@
 			silc_buffer_pull(&buf, 8);
 
 			purple_whiteboard_draw_line(wb, x, y, x + dx, y + dy,
-						  brush_color, brush_size);
+						    brush_color, brush_size);
 			x += dx;
 			y += dy;
 		}
@@ -253,8 +253,8 @@
 }
 
 static void
-silcpurple_wb_request(SilcClient client, const unsigned char *message, 
-		    SilcUInt32 message_len, SilcClientEntry sender, 
+silcpurple_wb_request(SilcClient client, const unsigned char *message,
+		    SilcUInt32 message_len, SilcClientEntry sender,
 		    SilcChannelEntry channel)
 {
 	char tmp[128];
@@ -406,16 +406,16 @@
 	/* Send the message */
 	if (wbs->type == 0) {
 		/* Private message */
-		silc_client_send_private_message(sg->client, sg->conn, 
-						 wbs->u.client, 
-						 SILC_MESSAGE_FLAG_DATA,
-						 packet->head, len, TRUE);
+		silc_client_send_private_message(sg->client, sg->conn,
+						 wbs->u.client,
+						 SILC_MESSAGE_FLAG_DATA, NULL,
+						 packet->head, len);
 	} else if (wbs->type == 1) {
 		/* Channel message. Channel private keys are not supported. */
 		silc_client_send_channel_message(sg->client, sg->conn,
 						 wbs->u.channel, NULL,
-						 SILC_MESSAGE_FLAG_DATA,
-						 packet->head, len, TRUE);
+						 SILC_MESSAGE_FLAG_DATA, NULL,
+						 packet->head, len);
 	}
 
 	silc_buffer_free(packet);
@@ -501,16 +501,16 @@
 	/* Send the message */
 	if (wbs->type == 0) {
 		/* Private message */
-		silc_client_send_private_message(sg->client, sg->conn, 
-						 wbs->u.client, 
-						 SILC_MESSAGE_FLAG_DATA,
-						 packet->head, len, TRUE);
+		silc_client_send_private_message(sg->client, sg->conn,
+						 wbs->u.client,
+						 SILC_MESSAGE_FLAG_DATA, NULL,
+						 packet->head, len);
 	} else if (wbs->type == 1) {
 		/* Channel message */
 		silc_client_send_channel_message(sg->client, sg->conn,
 						 wbs->u.channel, NULL,
-						 SILC_MESSAGE_FLAG_DATA,
-						 packet->head, len, TRUE);
+						 SILC_MESSAGE_FLAG_DATA, NULL,
+						 packet->head, len);
 	}
 
 	silc_buffer_free(packet);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/silc10/Makefile.am	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,36 @@
+EXTRA_DIST = README TODO Makefile.mingw
+
+pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
+
+SILCSOURCES = silc.c silcpurple.h buddy.c chat.c ft.c ops.c pk.c util.c wb.c wb.h
+
+AM_CFLAGS = $(st)
+
+libsilcpurple_la_LDFLAGS = -module -avoid-version
+
+if STATIC_SILC
+
+st = -DPURPLE_STATIC_PRPL $(SILC_CFLAGS)
+noinst_LIBRARIES = libsilcpurple.a
+pkg_LTLIBRARIES =
+
+libsilcpurple_a_SOURCES = $(SILCSOURCES)
+libsilcpurple_a_CFLAGS  = $(AM_CFLAGS)
+libsilcpurple_a_LIBADD  = $(SILC_LIBS)
+
+else
+
+st = $(SILC_CFLAGS)
+pkg_LTLIBRARIES = libsilcpurple.la
+noinst_LIBRARIES =
+
+libsilcpurple_la_SOURCES = $(SILCSOURCES)
+libsilcpurple_la_LIBADD  = $(GLIB_LIBS) $(SILC_LIBS)
+
+endif
+
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/libpurple \
+	-I$(top_builddir)/libpurple \
+	$(GLIB_CFLAGS) \
+	$(DEBUG_CFLAGS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/silc10/Makefile.mingw	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,91 @@
+#
+# Makefile.mingw
+#
+# Description: Makefile for win32 (mingw) version of libsilc protocol plugin
+#
+
+PIDGIN_TREE_TOP := ../../..
+include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+
+TARGET = libsilc
+NEEDED_DLLS =		$(SILC_TOOLKIT)/lib/silc.dll \
+			$(SILC_TOOLKIT)/lib/silcclient.dll
+TYPE = PLUGIN
+
+# Static or Plugin...
+ifeq ($(TYPE),STATIC)
+  DEFINES += -DSTATIC
+  DLL_INSTALL_DIR =	$(PURPLE_INSTALL_DIR)
+else
+ifeq ($(TYPE),PLUGIN)
+  DLL_INSTALL_DIR =	$(PURPLE_INSTALL_PLUGINS_DIR)
+endif
+endif
+
+##
+## INCLUDE PATHS
+##
+INCLUDE_PATHS +=	-I. \
+			-I$(GTK_TOP)/include \
+			-I$(GTK_TOP)/include/glib-2.0 \
+			-I$(GTK_TOP)/lib/glib-2.0/include \
+			-I$(PURPLE_TOP) \
+			-I$(PURPLE_TOP)/win32 \
+			-I$(PIDGIN_TREE_TOP) \
+			-I$(SILC_TOOLKIT)/include
+
+LIB_PATHS +=		-L$(GTK_TOP)/lib \
+			-L$(PURPLE_TOP) \
+			-L$(SILC_TOOLKIT)/lib
+
+##
+##  SOURCES, OBJECTS
+##
+C_SRC =			silc.c \
+			buddy.c \
+			chat.c \
+			ft.c \
+			ops.c \
+			pk.c \
+			util.c \
+			wb.c
+
+OBJECTS = $(C_SRC:%.c=%.o)
+
+##
+## LIBRARIES
+##
+LIBS = \
+			-lglib-2.0 \
+			-lws2_32 \
+			-lintl \
+			-lpurple \
+			-lsilc \
+			-lsilcclient
+
+include $(PIDGIN_COMMON_RULES)
+
+##
+## TARGET DEFINITIONS
+##
+.PHONY: all install clean
+
+all: $(TARGET).dll
+
+install: all $(DLL_INSTALL_DIR) $(PURPLE_INSTALL_DIR)
+	cp $(TARGET).dll $(DLL_INSTALL_DIR)
+	cp $(NEEDED_DLLS) $(PURPLE_INSTALL_DIR)
+
+$(OBJECTS): $(PURPLE_CONFIG_H)
+
+$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
+	$(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--image-base,0x64000000 -o $(TARGET).dll
+
+##
+## CLEAN RULES
+##
+clean:
+	rm -f $(OBJECTS)
+	rm -f $(TARGET).dll
+
+include $(PIDGIN_COMMON_TARGETS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/silc10/README	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,31 @@
+SILC Purple Plugin
+==================
+
+This is the Purple protocol plugin of the protocol called Secure Internet
+Live Conferencing (SILC).  The implementation will use the SILC Toolkit, 
+freely available from the http://silcnet.org/ site, for the actual SILC 
+protocol implementation.
+
+To include SILC into Purple, one needs to first compile and install 
+the SILC Toolkit.  It is done as follows:
+
+	./configure --enable-shared
+	make
+	make install
+
+This will compile shared libraries of the SILC Toolkit.  If the --prefix 
+is not given to ./configure, the binaries are installed into the 
+/usr/local/silc directory.
+
+Once the Toolkit is installed one needs to tell Purple's ./configure
+script where the SILC Toolkit is located.  It is done as simply as:
+
+	./configure
+
+if pkg-config is installed in your system.  If it is isn't it's done as:
+
+	./configure --with-silc-libs=/path/to/silc/lib
+		    --with-silc-includes=/path/to/silc/include
+
+If the SILC Toolkit cannot be found then the SILC protocol plugin will
+not be compiled.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/silc10/TODO	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,8 @@
+Features TODO (maybe)
+=====================
+
+Preferences
+	- Add joined channels to buddy list automatically (during
+	  session)
+	- Add joined channels to buddy list automatically permanently
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/silc10/buddy.c	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,1728 @@
+/*
+
+  silcpurple_buddy.c
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2004 Pekka Riikonen
+
+  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; version 2 of the License.
+
+  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.
+
+*/
+
+#include "silcincludes.h"
+#include "silcclient.h"
+#include "silcpurple.h"
+#include "wb.h"
+
+/***************************** Key Agreement *********************************/
+
+static void
+silcpurple_buddy_keyagr(PurpleBlistNode *node, gpointer data);
+
+static void
+silcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name,
+			 			 gboolean force_local);
+
+typedef struct {
+	char *nick;
+	PurpleConnection *gc;
+} *SilcPurpleResolve;
+
+static void
+silcpurple_buddy_keyagr_resolved(SilcClient client,
+			       SilcClientConnection conn,
+			       SilcClientEntry *clients,
+			       SilcUInt32 clients_count,
+			       void *context)
+{
+	PurpleConnection *gc = client->application;
+	SilcPurpleResolve r = context;
+	char tmp[256];
+
+	if (!clients) {
+		g_snprintf(tmp, sizeof(tmp),
+			   _("User %s is not present in the network"), r->nick);
+		purple_notify_error(gc, _("Key Agreement"),
+				  _("Cannot perform the key agreement"), tmp);
+		silc_free(r->nick);
+		silc_free(r);
+		return;
+	}
+
+	silcpurple_buddy_keyagr_do(gc, r->nick, FALSE);
+	silc_free(r->nick);
+	silc_free(r);
+}
+
+typedef struct {
+	gboolean responder;
+} *SilcPurpleKeyAgr;
+
+static void
+silcpurple_buddy_keyagr_cb(SilcClient client,
+			 SilcClientConnection conn,
+			 SilcClientEntry client_entry,
+			 SilcKeyAgreementStatus status,
+			 SilcSKEKeyMaterial *key,
+			 void *context)
+{
+	PurpleConnection *gc = client->application;
+	SilcPurple sg = gc->proto_data;
+	SilcPurpleKeyAgr a = context;
+
+	if (!sg->conn)
+		return;
+
+	switch (status) {
+	case SILC_KEY_AGREEMENT_OK:
+		{
+			PurpleConversation *convo;
+			char tmp[128];
+
+			/* Set the private key for this client */
+			silc_client_del_private_message_key(client, conn, client_entry);
+			silc_client_add_private_message_key_ske(client, conn, client_entry,
+								NULL, NULL, key, a->responder);
+			silc_ske_free_key_material(key);
+
+			
+			/* Open IM window */
+			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
+									client_entry->nickname, sg->account);
+			if (convo) {
+				/* we don't have windows in the core anymore...but we may want to
+				 * provide some method for asking the UI to show the window
+				purple_conv_window_show(purple_conversation_get_window(convo));
+				 */
+			} else {
+				convo = purple_conversation_new(PURPLE_CONV_TYPE_IM, sg->account,
+							      client_entry->nickname);
+			}
+			g_snprintf(tmp, sizeof(tmp), "%s [private key]", client_entry->nickname);
+			purple_conversation_set_title(convo, tmp);
+		}
+		break;
+
+	case SILC_KEY_AGREEMENT_ERROR:
+		purple_notify_error(gc, _("Key Agreement"),
+				  _("Error occurred during key agreement"), NULL);
+		break;
+
+	case SILC_KEY_AGREEMENT_FAILURE:
+		purple_notify_error(gc, _("Key Agreement"), _("Key Agreement failed"), NULL);
+		break;
+
+	case SILC_KEY_AGREEMENT_TIMEOUT:
+		purple_notify_error(gc, _("Key Agreement"),
+				  _("Timeout during key agreement"), NULL);
+		break;
+
+	case SILC_KEY_AGREEMENT_ABORTED:
+		purple_notify_error(gc, _("Key Agreement"),
+				  _("Key agreement was aborted"), NULL);
+		break;
+
+	case SILC_KEY_AGREEMENT_ALREADY_STARTED:
+		purple_notify_error(gc, _("Key Agreement"),
+				  _("Key agreement is already started"), NULL);
+		break;
+
+	case SILC_KEY_AGREEMENT_SELF_DENIED:
+		purple_notify_error(gc, _("Key Agreement"),
+				  _("Key agreement cannot be started with yourself"),
+				  NULL);
+		break;
+
+	default:
+		break;
+	}
+
+	silc_free(a);
+}
+
+static void
+silcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name,
+			 gboolean force_local)
+{
+	SilcPurple sg = gc->proto_data;
+	SilcClientEntry *clients;
+	SilcUInt32 clients_count;
+	char *local_ip = NULL, *remote_ip = NULL;
+	gboolean local = TRUE;
+	char *nickname;
+	SilcPurpleKeyAgr a;
+
+	if (!sg->conn || !name)
+		return;
+
+	if (!silc_parse_userfqdn(name, &nickname, NULL))
+		return;
+
+	/* Find client entry */
+	clients = silc_client_get_clients_local(sg->client, sg->conn, nickname, name,
+						&clients_count);
+	if (!clients) {
+		/* Resolve unknown user */
+		SilcPurpleResolve r = silc_calloc(1, sizeof(*r));
+		if (!r)
+			return;
+		r->nick = g_strdup(name);
+		r->gc = gc;
+		silc_client_get_clients(sg->client, sg->conn, nickname, NULL,
+					silcpurple_buddy_keyagr_resolved, r);
+		silc_free(nickname);
+		return;
+	}
+
+	/* Resolve the local IP from the outgoing socket connection.  We resolve
+	   it to check whether we have a private range IP address or public IP
+	   address.  If we have public then we will assume that we are not behind
+	   NAT and will provide automatically the point of connection to the
+	   agreement.  If we have private range address we assume that we are
+	   behind NAT and we let the responder provide the point of connection.
+
+	   The algorithm also checks the remote IP address of server connection.
+	   If it is private range address and we have private range address we
+	   assume that we are chatting in LAN and will provide the point of
+	   connection.
+
+	   Naturally this algorithm does not always get things right. */
+
+	if (silc_net_check_local_by_sock(sg->conn->sock->sock, NULL, &local_ip)) {
+		/* Check if the IP is private */
+		if (!force_local && silcpurple_ip_is_private(local_ip)) {
+			local = FALSE;
+
+			/* Local IP is private, resolve the remote server IP to see whether
+			   we are talking to Internet or just on LAN. */
+			if (silc_net_check_host_by_sock(sg->conn->sock->sock, NULL,
+							&remote_ip))
+				if (silcpurple_ip_is_private(remote_ip))
+					/* We assume we are in LAN.  Let's provide
+					   the connection point. */
+					local = TRUE;
+		}
+	}
+
+	if (force_local)
+		local = TRUE;
+
+	if (local && !local_ip)
+		local_ip = silc_net_localip();
+
+	a = silc_calloc(1, sizeof(*a));
+	if (!a)
+		return;
+	a->responder = local;
+
+	/* Send the key agreement request */
+	silc_client_send_key_agreement(sg->client, sg->conn, clients[0],
+				       local ? local_ip : NULL, NULL, 0, 60,
+				       silcpurple_buddy_keyagr_cb, a);
+
+	silc_free(local_ip);
+	silc_free(remote_ip);
+	silc_free(clients);
+}
+
+typedef struct {
+	SilcClient client;
+	SilcClientConnection conn;
+	SilcClientID client_id;
+	char *hostname;
+	SilcUInt16 port;
+} *SilcPurpleKeyAgrAsk;
+
+static void
+silcpurple_buddy_keyagr_request_cb(SilcPurpleKeyAgrAsk a, gint id)
+{
+	SilcPurpleKeyAgr ai;
+	SilcClientEntry client_entry;
+
+	if (id != 1)
+		goto out;
+
+	/* Get the client entry. */
+	client_entry = silc_client_get_client_by_id(a->client, a->conn,
+						    &a->client_id);
+	if (!client_entry) {
+		purple_notify_error(a->client->application, _("Key Agreement"),
+				  _("The remote user is not present in the network any more"),
+				  NULL);
+		goto out;
+	}
+
+	/* If the hostname was provided by the requestor perform the key agreement
+	   now.  Otherwise, we will send him a request to connect to us. */
+	if (a->hostname) {
+		ai = silc_calloc(1, sizeof(*ai));
+		if (!ai)
+			goto out;
+		ai->responder = FALSE;
+		silc_client_perform_key_agreement(a->client, a->conn, client_entry,
+						  a->hostname, a->port,
+						  silcpurple_buddy_keyagr_cb, ai);
+	} else {
+		/* Send request.  Force us as the point of connection since requestor
+		   did not provide the point of connection. */
+		silcpurple_buddy_keyagr_do(a->client->application,
+					 client_entry->nickname, TRUE);
+	}
+
+ out:
+	silc_free(a->hostname);
+	silc_free(a);
+}
+
+void silcpurple_buddy_keyagr_request(SilcClient client,
+				   SilcClientConnection conn,
+				   SilcClientEntry client_entry,
+				   const char *hostname, SilcUInt16 port)
+{
+	char tmp[128], tmp2[128];
+	SilcPurpleKeyAgrAsk a;
+	PurpleConnection *gc = client->application;
+
+	g_snprintf(tmp, sizeof(tmp),
+		   _("Key agreement request received from %s. Would you like to "
+		     "perform the key agreement?"), client_entry->nickname);
+	if (hostname)
+		g_snprintf(tmp2, sizeof(tmp2),
+			   _("The remote user is waiting key agreement on:\n"
+			     "Remote host: %s\nRemote port: %d"), hostname, port);
+
+	a = silc_calloc(1, sizeof(*a));
+	if (!a)
+		return;
+	a->client = client;
+	a->conn = conn;
+	a->client_id = *client_entry->id;
+	if (hostname)
+		a->hostname = strdup(hostname);
+	a->port = port;
+
+	purple_request_action(client->application, _("Key Agreement Request"), tmp,
+			    hostname ? tmp2 : NULL, 1, gc->account, client_entry->nickname,
+				NULL, a, 2, _("Yes"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb),
+			    _("No"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb));
+}
+
+static void
+silcpurple_buddy_keyagr(PurpleBlistNode *node, gpointer data)
+{
+	PurpleBuddy *buddy;
+
+	buddy = (PurpleBuddy *)node;
+	silcpurple_buddy_keyagr_do(buddy->account->gc, buddy->name, FALSE);
+}
+
+
+/**************************** Static IM Key **********************************/
+
+static void
+silcpurple_buddy_resetkey(PurpleBlistNode *node, gpointer data)
+{
+	PurpleBuddy *b;
+	PurpleConnection *gc;
+        SilcPurple sg;
+	char *nickname;
+	SilcClientEntry *clients;
+	SilcUInt32 clients_count;
+
+	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+
+	b = (PurpleBuddy *) node;
+	gc = purple_account_get_connection(b->account);
+	sg = gc->proto_data;
+
+	if (!silc_parse_userfqdn(b->name, &nickname, NULL))
+		return;
+
+	/* Find client entry */
+	clients = silc_client_get_clients_local(sg->client, sg->conn,
+						nickname, b->name,
+						&clients_count);
+	if (!clients) {
+		silc_free(nickname);
+		return;
+	}
+
+	clients[0]->prv_resp = FALSE;
+	silc_client_del_private_message_key(sg->client, sg->conn,
+					    clients[0]);
+	silc_free(clients);
+	silc_free(nickname);
+}
+
+typedef struct {
+	SilcClient client;
+	SilcClientConnection conn;
+	SilcClientID client_id;
+} *SilcPurplePrivkey;
+
+static void
+silcpurple_buddy_privkey(PurpleConnection *gc, const char *name);
+
+static void
+silcpurple_buddy_privkey_cb(SilcPurplePrivkey p, const char *passphrase)
+{
+	SilcClientEntry client_entry;
+
+        if (!passphrase || !(*passphrase)) {
+                silc_free(p);
+                return;
+        }
+
+	/* Get the client entry. */
+	client_entry = silc_client_get_client_by_id(p->client, p->conn,
+						    &p->client_id);
+	if (!client_entry) {
+		purple_notify_error(p->client->application, _("IM With Password"),
+				  _("The remote user is not present in the network any more"),
+				  NULL);
+		silc_free(p);
+		return;
+	}
+
+	/* Set the private message key */
+	silc_client_del_private_message_key(p->client, p->conn,
+					    client_entry);
+	silc_client_add_private_message_key(p->client, p->conn,
+					    client_entry, NULL, NULL,
+					    (unsigned char *)passphrase,
+					    strlen(passphrase), FALSE,
+					    client_entry->prv_resp);
+	if (!client_entry->prv_resp)
+		silc_client_send_private_message_key_request(p->client,
+							     p->conn,
+							     client_entry);
+        silc_free(p);
+}
+
+static void
+silcpurple_buddy_privkey_resolved(SilcClient client,
+				SilcClientConnection conn,
+				SilcClientEntry *clients,
+				SilcUInt32 clients_count,
+				void *context)
+{
+	char tmp[256];
+
+	if (!clients) {
+		g_snprintf(tmp, sizeof(tmp),
+			   _("User %s is not present in the network"),
+			   (const char *)context);
+		purple_notify_error(client->application, _("IM With Password"),
+				  _("Cannot set IM key"), tmp);
+		g_free(context);
+		return;
+	}
+
+	silcpurple_buddy_privkey(client->application, context);
+	silc_free(context);
+}
+
+static void
+silcpurple_buddy_privkey(PurpleConnection *gc, const char *name)
+{
+	SilcPurple sg = gc->proto_data;
+	char *nickname;
+	SilcPurplePrivkey p;
+	SilcClientEntry *clients;
+	SilcUInt32 clients_count;
+
+	if (!name)
+		return;
+	if (!silc_parse_userfqdn(name, &nickname, NULL))
+		return;
+
+	/* Find client entry */
+	clients = silc_client_get_clients_local(sg->client, sg->conn,
+						nickname, name,
+						&clients_count);
+	if (!clients) {
+		silc_client_get_clients(sg->client, sg->conn, nickname, NULL,
+					silcpurple_buddy_privkey_resolved,
+					g_strdup(name));
+		silc_free(nickname);
+		return;
+	}
+
+	p = silc_calloc(1, sizeof(*p));
+	if (!p)
+		return;
+	p->client = sg->client;
+	p->conn = sg->conn;
+	p->client_id = *clients[0]->id;
+	purple_request_input(gc, _("IM With Password"), NULL,
+	                     _("Set IM Password"), NULL, FALSE, TRUE, NULL,
+	                     _("OK"), G_CALLBACK(silcpurple_buddy_privkey_cb),
+	                     _("Cancel"), G_CALLBACK(silcpurple_buddy_privkey_cb),
+	                     gc->account, NULL, NULL, p);
+
+	silc_free(clients);
+	silc_free(nickname);
+}
+
+static void
+silcpurple_buddy_privkey_menu(PurpleBlistNode *node, gpointer data)
+{
+	PurpleBuddy *buddy;
+	PurpleConnection *gc;
+
+	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+
+	buddy = (PurpleBuddy *) node;
+	gc = purple_account_get_connection(buddy->account);
+
+	silcpurple_buddy_privkey(gc, buddy->name);
+}
+
+
+/**************************** Get Public Key *********************************/
+
+typedef struct {
+	SilcClient client;
+	SilcClientConnection conn;
+	SilcClientID client_id;
+} *SilcPurpleBuddyGetkey;
+
+static void
+silcpurple_buddy_getkey(PurpleConnection *gc, const char *name);
+
+static void
+silcpurple_buddy_getkey_cb(SilcPurpleBuddyGetkey g,
+			 SilcClientCommandReplyContext cmd)
+{
+	SilcClientEntry client_entry;
+	unsigned char *pk;
+	SilcUInt32 pk_len;
+
+	/* Get the client entry. */
+	client_entry = silc_client_get_client_by_id(g->client, g->conn,
+						    &g->client_id);
+	if (!client_entry) {
+		purple_notify_error(g->client->application, _("Get Public Key"),
+				  _("The remote user is not present in the network any more"),
+				  NULL);
+		silc_free(g);
+		return;
+	}
+
+	if (!client_entry->public_key) {
+		silc_free(g);
+		return;
+	}
+
+	/* Now verify the public key */
+	pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len);
+	silcpurple_verify_public_key(g->client, g->conn, client_entry->nickname,
+				   SILC_SOCKET_TYPE_CLIENT,
+				   pk, pk_len, SILC_SKE_PK_TYPE_SILC,
+				   NULL, NULL);
+	silc_free(pk);
+	silc_free(g);
+}
+
+static void
+silcpurple_buddy_getkey_resolved(SilcClient client,
+			       SilcClientConnection conn,
+			       SilcClientEntry *clients,
+			       SilcUInt32 clients_count,
+			       void *context)
+{
+	char tmp[256];
+
+	if (!clients) {
+		g_snprintf(tmp, sizeof(tmp),
+			   _("User %s is not present in the network"),
+			   (const char *)context);
+		purple_notify_error(client->application, _("Get Public Key"),
+				  _("Cannot fetch the public key"), tmp);
+		g_free(context);
+		return;
+	}
+
+	silcpurple_buddy_getkey(client->application, context);
+	silc_free(context);
+}
+
+static void
+silcpurple_buddy_getkey(PurpleConnection *gc, const char *name)
+{
+	SilcPurple sg = gc->proto_data;
+	SilcClient client = sg->client;
+	SilcClientConnection conn = sg->conn;
+	SilcClientEntry *clients;
+	SilcUInt32 clients_count;
+	SilcPurpleBuddyGetkey g;
+	char *nickname;
+
+	if (!name)
+		return;
+
+	if (!silc_parse_userfqdn(name, &nickname, NULL))
+		return;
+
+	/* Find client entry */
+	clients = silc_client_get_clients_local(client, conn, nickname, name,
+						&clients_count);
+	if (!clients) {
+		silc_client_get_clients(client, conn, nickname, NULL,
+					silcpurple_buddy_getkey_resolved,
+					g_strdup(name));
+		silc_free(nickname);
+		return;
+	}
+
+	/* Call GETKEY */
+	g = silc_calloc(1, sizeof(*g));
+	if (!g)
+		return;
+	g->client = client;
+	g->conn = conn;
+	g->client_id = *clients[0]->id;
+	silc_client_command_call(client, conn, NULL, "GETKEY",
+				 clients[0]->nickname, NULL);
+	silc_client_command_pending(conn, SILC_COMMAND_GETKEY,
+				    conn->cmd_ident,
+				    (SilcCommandCb)silcpurple_buddy_getkey_cb, g);
+	silc_free(clients);
+	silc_free(nickname);
+}
+
+static void
+silcpurple_buddy_getkey_menu(PurpleBlistNode *node, gpointer data)
+{
+	PurpleBuddy *buddy;
+	PurpleConnection *gc;
+
+	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+
+	buddy = (PurpleBuddy *) node;
+	gc = purple_account_get_connection(buddy->account);
+
+	silcpurple_buddy_getkey(gc, buddy->name);
+}
+
+static void
+silcpurple_buddy_showkey(PurpleBlistNode *node, gpointer data)
+{
+	PurpleBuddy *b;
+	PurpleConnection *gc;
+	SilcPurple sg;
+	SilcPublicKey public_key;
+	const char *pkfile;
+
+	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+
+	b = (PurpleBuddy *) node;
+	gc = purple_account_get_connection(b->account);
+	sg = gc->proto_data;
+
+	pkfile = purple_blist_node_get_string(node, "public-key");
+	if (!silc_pkcs_load_public_key(pkfile, &public_key, SILC_PKCS_FILE_PEM) &&
+	    !silc_pkcs_load_public_key(pkfile, &public_key, SILC_PKCS_FILE_BIN)) {
+		purple_notify_error(gc,
+				  _("Show Public Key"),
+				  _("Could not load public key"), NULL);
+		return;
+	}
+
+	silcpurple_show_public_key(sg, b->name, public_key, NULL, NULL);
+	silc_pkcs_public_key_free(public_key);
+}
+
+
+/**************************** Buddy routines *********************************/
+
+/* The buddies are implemented by using the WHOIS and WATCH commands that
+   can be used to search users by their public key.  Since nicknames aren't
+   unique in SILC we cannot trust the buddy list using their nickname.  We
+   associate public keys to buddies and use those to search and watch
+   in the network.
+
+   The problem is that Purple does not return PurpleBuddy contexts to the
+   callbacks but the buddy names.  Naturally, this is not going to work
+   with SILC.  But, for now, we have to do what we can... */
+
+typedef struct {
+	SilcClient client;
+	SilcClientConnection conn;
+	SilcClientID client_id;
+	PurpleBuddy *b;
+	unsigned char *offline_pk;
+	SilcUInt32 offline_pk_len;
+	unsigned int offline        : 1;
+	unsigned int pubkey_search  : 1;
+	unsigned int init           : 1;
+} *SilcPurpleBuddyRes;
+
+static void
+silcpurple_add_buddy_ask_pk_cb(SilcPurpleBuddyRes r, gint id);
+static void
+silcpurple_add_buddy_resolved(SilcClient client,
+			    SilcClientConnection conn,
+			    SilcClientEntry *clients,
+			    SilcUInt32 clients_count,
+			    void *context);
+
+void silcpurple_get_info(PurpleConnection *gc, const char *who)
+{
+	SilcPurple sg = gc->proto_data;
+	SilcClient client = sg->client;
+	SilcClientConnection conn = sg->conn;
+	SilcClientEntry client_entry;
+	PurpleBuddy *b;
+	const char *filename, *nick = who;
+	char tmp[256];
+
+	if (!who)
+		return;
+	if (strlen(who) > 1 && who[0] == '@')
+		nick = who + 1;
+	if (strlen(who) > 1 && who[0] == '*')
+		nick = who + 1;
+	if (strlen(who) > 2 && who[0] == '*' && who[1] == '@')
+		nick = who + 2;
+
+	b = purple_find_buddy(gc->account, nick);
+	if (b) {
+		/* See if we have this buddy's public key.  If we do use that
+		   to search the details. */
+		filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key");
+		if (filename) {
+			/* Call WHOIS.  The user info is displayed in the WHOIS
+			   command reply. */
+			silc_client_command_call(client, conn, NULL, "WHOIS",
+						 "-details", "-pubkey", filename, NULL);
+			return;
+		}
+
+		if (!b->proto_data) {
+			g_snprintf(tmp, sizeof(tmp),
+				   _("User %s is not present in the network"), b->name);
+			purple_notify_error(gc, _("User Information"),
+					  _("Cannot get user information"), tmp);
+			return;
+		}
+
+		client_entry = silc_client_get_client_by_id(client, conn, b->proto_data);
+		if (client_entry) {
+			/* Call WHOIS.  The user info is displayed in the WHOIS
+			   command reply. */
+			silc_client_command_call(client, conn, NULL, "WHOIS",
+						 client_entry->nickname, "-details", NULL);
+		}
+	} else {
+		/* Call WHOIS just with nickname. */
+		silc_client_command_call(client, conn, NULL, "WHOIS", nick, NULL);
+	}
+}
+
+static void
+silcpurple_add_buddy_pk_no(SilcPurpleBuddyRes r)
+{
+	char tmp[512];
+	g_snprintf(tmp, sizeof(tmp), _("The %s buddy is not trusted"),
+		   r->b->name);
+	purple_notify_error(r->client->application, _("Add Buddy"), tmp,
+			  _("You cannot receive buddy notifications until you "
+			    "import his/her public key.  You can use the Get Public Key "
+			    "command to get the public key."));
+	purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
+}
+
+static void
+silcpurple_add_buddy_save(bool success, void *context)
+{
+	SilcPurpleBuddyRes r = context;
+	PurpleBuddy *b = r->b;
+	SilcClient client = r->client;
+	SilcClientEntry client_entry;
+	SilcAttributePayload attr;
+	SilcAttribute attribute;
+	SilcVCardStruct vcard;
+	SilcAttributeObjMime message, extension;
+#ifdef SILC_ATTRIBUTE_USER_ICON
+	SilcAttributeObjMime usericon;
+#endif
+	SilcAttributeObjPk serverpk, usersign, serversign;
+	gboolean usign_success = TRUE, ssign_success = TRUE;
+	char filename[512], filename2[512], *fingerprint = NULL, *tmp;
+	SilcUInt32 len;
+	int i;
+
+	if (!success) {
+		/* The user did not trust the public key. */
+		silcpurple_add_buddy_pk_no(r);
+		silc_free(r);
+		return;
+	}
+
+	if (r->offline) {
+		/* User is offline.  Associate the imported public key with
+		   this user. */
+		fingerprint = silc_hash_fingerprint(NULL, r->offline_pk,
+						    r->offline_pk_len);
+		for (i = 0; i < strlen(fingerprint); i++)
+			if (fingerprint[i] == ' ')
+				fingerprint[i] = '_';
+		g_snprintf(filename, sizeof(filename) - 1,
+			   "%s" G_DIR_SEPARATOR_S "clientkeys" G_DIR_SEPARATOR_S "clientkey_%s.pub",
+			   silcpurple_silcdir(), fingerprint);
+		purple_blist_node_set_string((PurpleBlistNode *)b, "public-key", filename);
+		purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
+		silc_free(fingerprint);
+		silc_free(r->offline_pk);
+		silc_free(r);
+		return;
+	}
+
+	/* Get the client entry. */
+	client_entry = silc_client_get_client_by_id(r->client, r->conn,
+						    &r->client_id);
+	if (!client_entry) {
+		silc_free(r);
+		return;
+	}
+
+	memset(&vcard, 0, sizeof(vcard));
+	memset(&message, 0, sizeof(message));
+	memset(&extension, 0, sizeof(extension));
+#ifdef SILC_ATTRIBUTE_USER_ICON
+	memset(&usericon, 0, sizeof(usericon));
+#endif
+	memset(&serverpk, 0, sizeof(serverpk));
+	memset(&usersign, 0, sizeof(usersign));
+	memset(&serversign, 0, sizeof(serversign));
+
+	/* Now that we have the public key and we trust it now we
+	   save the attributes of the buddy and update its status. */
+
+	if (client_entry->attrs) {
+		silc_dlist_start(client_entry->attrs);
+		while ((attr = silc_dlist_get(client_entry->attrs))
+		       != SILC_LIST_END) {
+			attribute = silc_attribute_get_attribute(attr);
+
+			switch (attribute) {
+			case SILC_ATTRIBUTE_USER_INFO:
+				if (!silc_attribute_get_object(attr, (void *)&vcard,
+							       sizeof(vcard)))
+					continue;
+				break;
+
+			case SILC_ATTRIBUTE_STATUS_MESSAGE:
+				if (!silc_attribute_get_object(attr, (void *)&message,
+							       sizeof(message)))
+					continue;
+				break;
+
+			case SILC_ATTRIBUTE_EXTENSION:
+				if (!silc_attribute_get_object(attr, (void *)&extension,
+							       sizeof(extension)))
+					continue;
+				break;
+
+#ifdef SILC_ATTRIBUTE_USER_ICON
+			case SILC_ATTRIBUTE_USER_ICON:
+				if (!silc_attribute_get_object(attr, (void *)&usericon,
+							       sizeof(usericon)))
+					continue;
+				break;
+#endif
+
+			case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY:
+				if (serverpk.type)
+					continue;
+				if (!silc_attribute_get_object(attr, (void *)&serverpk,
+							       sizeof(serverpk)))
+					continue;
+				break;
+
+			case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE:
+				if (usersign.data)
+					continue;
+				if (!silc_attribute_get_object(attr, (void *)&usersign,
+							       sizeof(usersign)))
+					continue;
+				break;
+
+			case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE:
+				if (serversign.data)
+					continue;
+				if (!silc_attribute_get_object(attr, (void *)&serversign,
+							       sizeof(serversign)))
+					continue;
+				break;
+
+			default:
+				break;
+			}
+		}
+	}
+
+	/* Verify the attribute signatures */
+
+	if (usersign.data) {
+		SilcPKCS pkcs;
+		unsigned char *verifyd;
+		SilcUInt32 verify_len;
+
+		silc_pkcs_alloc((unsigned char*)"rsa", &pkcs);
+		verifyd = silc_attribute_get_verify_data(client_entry->attrs,
+							 FALSE, &verify_len);
+		if (verifyd && silc_pkcs_public_key_set(pkcs, client_entry->public_key)){
+			if (!silc_pkcs_verify_with_hash(pkcs, client->sha1hash,
+							usersign.data,
+							usersign.data_len,
+							verifyd, verify_len))
+				usign_success = FALSE;
+		}
+		silc_free(verifyd);
+	}
+
+	if (serversign.data && !strcmp(serverpk.type, "silc-rsa")) {
+		SilcPublicKey public_key;
+		SilcPKCS pkcs;
+		unsigned char *verifyd;
+		SilcUInt32 verify_len;
+
+		if (silc_pkcs_public_key_decode(serverpk.data, serverpk.data_len,
+						&public_key)) {
+			silc_pkcs_alloc((unsigned char *)"rsa", &pkcs);
+			verifyd = silc_attribute_get_verify_data(client_entry->attrs,
+								 TRUE, &verify_len);
+			if (verifyd && silc_pkcs_public_key_set(pkcs, public_key)) {
+				if (!silc_pkcs_verify_with_hash(pkcs, client->sha1hash,
+							       serversign.data,
+							       serversign.data_len,
+							       verifyd, verify_len))
+					ssign_success = FALSE;
+			}
+			silc_pkcs_public_key_free(public_key);
+			silc_free(verifyd);
+		}
+	}
+
+	fingerprint = silc_fingerprint(client_entry->fingerprint,
+				       client_entry->fingerprint_len);
+	for (i = 0; i < strlen(fingerprint); i++)
+		if (fingerprint[i] == ' ')
+			fingerprint[i] = '_';
+
+	if (usign_success || ssign_success) {
+		struct passwd *pw;
+		struct stat st;
+
+		memset(filename2, 0, sizeof(filename2));
+
+		/* Filename for dir */
+		tmp = fingerprint + strlen(fingerprint) - 9;
+		g_snprintf(filename, sizeof(filename) - 1,
+			   "%s" G_DIR_SEPARATOR_S "friends" G_DIR_SEPARATOR_S "%s",
+			   silcpurple_silcdir(), tmp);
+
+		pw = getpwuid(getuid());
+		if (!pw)
+			return;
+
+		/* Create dir if it doesn't exist */
+		if ((g_stat(filename, &st)) == -1) {
+			if (errno == ENOENT) {
+				if (pw->pw_uid == geteuid())
+					g_mkdir(filename, 0755);
+			}
+		}
+
+		/* Save VCard */
+		g_snprintf(filename2, sizeof(filename2) - 1,
+			   "%s" G_DIR_SEPARATOR_S "vcard", filename);
+		if (vcard.full_name) {
+			tmp = (char *)silc_vcard_encode(&vcard, &len);
+			silc_file_writefile(filename2, tmp, len);
+			silc_free(tmp);
+		}
+
+		/* Save status message */
+		if (message.mime) {
+			memset(filename2, 0, sizeof(filename2));
+			g_snprintf(filename2, sizeof(filename2) - 1,
+				   "%s" G_DIR_SEPARATOR_S "status_message.mime",
+				   filename);
+			silc_file_writefile(filename2, (char *)message.mime,
+					    message.mime_len);
+		}
+
+		/* Save extension data */
+		if (extension.mime) {
+			memset(filename2, 0, sizeof(filename2));
+			g_snprintf(filename2, sizeof(filename2) - 1,
+				   "%s" G_DIR_SEPARATOR_S "extension.mime",
+				   filename);
+			silc_file_writefile(filename2, (char *)extension.mime,
+					    extension.mime_len);
+		}
+
+#ifdef SILC_ATTRIBUTE_USER_ICON
+		/* Save user icon */
+		if (usericon.mime) {
+			SilcMime m = silc_mime_decode(usericon.mime,
+						      usericon.mime_len);
+			if (m) {
+				const char *type = silc_mime_get_field(m, "Content-Type");
+				if (!strcmp(type, "image/jpeg") ||
+				    !strcmp(type, "image/gif") ||
+				    !strcmp(type, "image/bmp") ||
+				    !strcmp(type, "image/png")) {
+					const unsigned char *data;
+					SilcUInt32 data_len;
+					data = silc_mime_get_data(m, &data_len);
+					if (data) {
+						/* TODO: Check if SILC gives us something to use as the checksum instead */
+						purple_buddy_icons_set_for_user(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), g_memdup(data, data_len), data_len, NULL);
+					}
+				}
+				silc_mime_free(m);
+			}
+		}
+#endif
+	}
+
+	/* Save the public key path to buddy properties, as it is used
+	   to identify the buddy in the network (and not the nickname). */
+	memset(filename, 0, sizeof(filename));
+	g_snprintf(filename, sizeof(filename) - 1,
+		   "%s" G_DIR_SEPARATOR_S "clientkeys" G_DIR_SEPARATOR_S "clientkey_%s.pub",
+		   silcpurple_silcdir(), fingerprint);
+	purple_blist_node_set_string((PurpleBlistNode *)b, "public-key", filename);
+
+	/* Update online status */
+	purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL);
+
+	/* Finally, start watching this user so we receive its status
+	   changes from the server */
+	g_snprintf(filename2, sizeof(filename2) - 1, "+%s", filename);
+	silc_client_command_call(r->client, r->conn, NULL, "WATCH", "-pubkey",
+				 filename2, NULL);
+
+	silc_free(fingerprint);
+	silc_free(r);
+}
+
+static void
+silcpurple_add_buddy_ask_import(void *user_data, const char *name)
+{
+	SilcPurpleBuddyRes r = (SilcPurpleBuddyRes)user_data;
+	SilcPublicKey public_key;
+
+	/* Load the public key */
+	if (!silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_PEM) &&
+	    !silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_BIN)) {
+		silcpurple_add_buddy_ask_pk_cb(r, 0);
+		purple_notify_error(r->client->application,
+				  _("Add Buddy"), _("Could not load public key"), NULL);
+		return;
+	}
+
+	/* Now verify the public key */
+	r->offline_pk = silc_pkcs_public_key_encode(public_key, &r->offline_pk_len);
+	silcpurple_verify_public_key(r->client, r->conn, r->b->name,
+				   SILC_SOCKET_TYPE_CLIENT,
+				   r->offline_pk, r->offline_pk_len,
+				   SILC_SKE_PK_TYPE_SILC,
+				   silcpurple_add_buddy_save, r);
+}
+
+static void
+silcpurple_add_buddy_ask_pk_cancel(void *user_data, const char *name)
+{
+	SilcPurpleBuddyRes r = (SilcPurpleBuddyRes)user_data;
+
+	/* The user did not import public key.  The buddy is unusable. */
+	silcpurple_add_buddy_pk_no(r);
+	silc_free(r);
+}
+
+static void
+silcpurple_add_buddy_ask_pk_cb(SilcPurpleBuddyRes r, gint id)
+{
+	if (id != 0) {
+		/* The user did not import public key.  The buddy is unusable. */
+		silcpurple_add_buddy_pk_no(r);
+		silc_free(r);
+		return;
+	}
+
+	/* Open file selector to select the public key. */
+	purple_request_file(r->client->application, _("Open..."), NULL, FALSE,
+			  G_CALLBACK(silcpurple_add_buddy_ask_import),
+			  G_CALLBACK(silcpurple_add_buddy_ask_pk_cancel),
+			  purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r);
+
+}
+
+static void
+silcpurple_add_buddy_ask_pk(SilcPurpleBuddyRes r)
+{
+	char tmp[512];
+	g_snprintf(tmp, sizeof(tmp), _("The %s buddy is not present in the network"),
+		   r->b->name);
+	purple_request_action(r->client->application, _("Add Buddy"), tmp,
+			    _("To add the buddy you must import his/her public key. "
+			      "Press Import to import a public key."), 0,
+				  purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r, 2,
+			    _("Cancel"), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb),
+			    _("_Import..."), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb));
+}
+
+static void
+silcpurple_add_buddy_getkey_cb(SilcPurpleBuddyRes r,
+			     SilcClientCommandReplyContext cmd)
+{
+	SilcClientEntry client_entry;
+	unsigned char *pk;
+	SilcUInt32 pk_len;
+
+	/* Get the client entry. */
+	client_entry = silc_client_get_client_by_id(r->client, r->conn,
+						    &r->client_id);
+	if (!client_entry || !client_entry->public_key) {
+		/* The buddy is offline/nonexistent. We will require user
+		   to associate a public key with the buddy or the buddy
+		   cannot be added. */
+		r->offline = TRUE;
+		silcpurple_add_buddy_ask_pk(r);
+		return;
+	}
+
+	/* Now verify the public key */
+	pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len);
+	silcpurple_verify_public_key(r->client, r->conn, client_entry->nickname,
+				   SILC_SOCKET_TYPE_CLIENT,
+				   pk, pk_len, SILC_SKE_PK_TYPE_SILC,
+				   silcpurple_add_buddy_save, r);
+	silc_free(pk);
+}
+
+static void
+silcpurple_add_buddy_select_cb(SilcPurpleBuddyRes r, PurpleRequestFields *fields)
+{
+	PurpleRequestField *f;
+	const GList *list;
+	SilcClientEntry client_entry;
+
+	f = purple_request_fields_get_field(fields, "list");
+	list = purple_request_field_list_get_selected(f);
+	if (!list) {
+		/* The user did not select any user. */
+		silcpurple_add_buddy_pk_no(r);
+		silc_free(r);
+		return;
+	}
+
+	client_entry = purple_request_field_list_get_data(f, list->data);
+	silcpurple_add_buddy_resolved(r->client, r->conn, &client_entry, 1, r);
+}
+
+static void
+silcpurple_add_buddy_select_cancel(SilcPurpleBuddyRes r, PurpleRequestFields *fields)
+{
+	/* The user did not select any user. */
+	silcpurple_add_buddy_pk_no(r);
+	silc_free(r);
+}
+
+static void
+silcpurple_add_buddy_select(SilcPurpleBuddyRes r,
+			  SilcClientEntry *clients,
+			  SilcUInt32 clients_count)
+{
+	PurpleRequestFields *fields;
+	PurpleRequestFieldGroup *g;
+	PurpleRequestField *f;
+	char tmp[512], tmp2[128];
+	int i;
+	char *fingerprint;
+
+	fields = purple_request_fields_new();
+	g = purple_request_field_group_new(NULL);
+	f = purple_request_field_list_new("list", NULL);
+	purple_request_field_group_add_field(g, f);
+	purple_request_field_list_set_multi_select(f, FALSE);
+	purple_request_fields_add_group(fields, g);
+
+	for (i = 0; i < clients_count; i++) {
+		fingerprint = NULL;
+		if (clients[i]->fingerprint) {
+			fingerprint = silc_fingerprint(clients[i]->fingerprint,
+						       clients[i]->fingerprint_len);
+			g_snprintf(tmp2, sizeof(tmp2), "\n%s", fingerprint);
+		}
+		g_snprintf(tmp, sizeof(tmp), "%s - %s (%s@%s)%s",
+			   clients[i]->realname, clients[i]->nickname,
+			   clients[i]->username, clients[i]->hostname ?
+			   clients[i]->hostname : "",
+			   fingerprint ? tmp2 : "");
+		purple_request_field_list_add(f, tmp, clients[i]);
+		silc_free(fingerprint);
+	}
+
+	purple_request_fields(r->client->application, _("Add Buddy"),
+				_("Select correct user"),
+				r->pubkey_search
+					? _("More than one user was found with the same public key. Select "
+						"the correct user from the list to add to the buddy list.")
+					: _("More than one user was found with the same name. Select "
+						"the correct user from the list to add to the buddy list."),
+				fields,
+				_("OK"), G_CALLBACK(silcpurple_add_buddy_select_cb),
+				_("Cancel"), G_CALLBACK(silcpurple_add_buddy_select_cancel),
+				purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r);
+}
+
+static void
+silcpurple_add_buddy_resolved(SilcClient client,
+			    SilcClientConnection conn,
+			    SilcClientEntry *clients,
+			    SilcUInt32 clients_count,
+			    void *context)
+{
+	SilcPurpleBuddyRes r = context;
+	PurpleBuddy *b = r->b;
+	SilcAttributePayload pub;
+	SilcAttributeObjPk userpk;
+	unsigned char *pk;
+	SilcUInt32 pk_len;
+	const char *filename;
+
+	filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key");
+
+	/* If the buddy is offline/nonexistent, we will require user
+	   to associate a public key with the buddy or the buddy
+	   cannot be added. */
+	if (!clients_count) {
+		if (r->init) {
+			silc_free(r);
+			return;
+		}
+
+		r->offline = TRUE;
+		/* If the user has already associated a public key, try loading it
+		 * before prompting the user to load it again */
+		if (filename != NULL)
+			silcpurple_add_buddy_ask_import(r, filename);
+		else
+			silcpurple_add_buddy_ask_pk(r);
+		return;
+	}
+
+	/* If more than one client was found with nickname, we need to verify
+	   from user which one is the correct. */
+	if (clients_count > 1 && !r->pubkey_search) {
+		if (r->init) {
+			silc_free(r);
+			return;
+		}
+
+		silcpurple_add_buddy_select(r, clients, clients_count);
+		return;
+	}
+
+	/* If we searched using public keys and more than one entry was found
+	   the same person is logged on multiple times. */
+	if (clients_count > 1 && r->pubkey_search && b->name) {
+		if (r->init) {
+			/* Find the entry that closest matches to the
+			   buddy nickname. */
+			int i;
+			for (i = 0; i < clients_count; i++) {
+				if (!strncasecmp(b->name, clients[i]->nickname,
+						 strlen(b->name))) {
+					clients[0] = clients[i];
+					break;
+				}
+			}
+		} else {
+			/* Verify from user which one is correct */
+			silcpurple_add_buddy_select(r, clients, clients_count);
+			return;
+		}
+	}
+
+	/* The client was found.  Now get its public key and verify
+	   that before adding the buddy. */
+	memset(&userpk, 0, sizeof(userpk));
+	b->proto_data = silc_memdup(clients[0]->id, sizeof(*clients[0]->id));
+	r->client_id = *clients[0]->id;
+
+	/* Get the public key from attributes, if not present then
+	   resolve it with GETKEY unless we have it cached already. */
+	if (clients[0]->attrs && !clients[0]->public_key) {
+		pub = silcpurple_get_attr(clients[0]->attrs,
+					SILC_ATTRIBUTE_USER_PUBLIC_KEY);
+		if (!pub || !silc_attribute_get_object(pub, (void *)&userpk,
+						       sizeof(userpk))) {
+			/* Get public key with GETKEY */
+			silc_client_command_call(client, conn, NULL,
+						 "GETKEY", clients[0]->nickname, NULL);
+			silc_client_command_pending(conn, SILC_COMMAND_GETKEY,
+						    conn->cmd_ident,
+						    (SilcCommandCb)silcpurple_add_buddy_getkey_cb,
+						    r);
+			return;
+		}
+		if (!silc_pkcs_public_key_decode(userpk.data, userpk.data_len,
+						 &clients[0]->public_key))
+			return;
+		silc_free(userpk.data);
+	} else if (filename && !clients[0]->public_key) {
+		if (!silc_pkcs_load_public_key(filename, &clients[0]->public_key,
+					       SILC_PKCS_FILE_PEM) &&
+		    !silc_pkcs_load_public_key(filename, &clients[0]->public_key,
+					       SILC_PKCS_FILE_BIN)) {
+			/* Get public key with GETKEY */
+			silc_client_command_call(client, conn, NULL,
+						 "GETKEY", clients[0]->nickname, NULL);
+			silc_client_command_pending(conn, SILC_COMMAND_GETKEY,
+						    conn->cmd_ident,
+						    (SilcCommandCb)silcpurple_add_buddy_getkey_cb,
+						    r);
+			return;
+		}
+	} else if (!clients[0]->public_key) {
+		/* Get public key with GETKEY */
+		silc_client_command_call(client, conn, NULL,
+					 "GETKEY", clients[0]->nickname, NULL);
+		silc_client_command_pending(conn, SILC_COMMAND_GETKEY,
+					    conn->cmd_ident,
+					    (SilcCommandCb)silcpurple_add_buddy_getkey_cb,
+					    r);
+		return;
+	}
+
+	/* We have the public key, verify it. */
+	pk = silc_pkcs_public_key_encode(clients[0]->public_key, &pk_len);
+	silcpurple_verify_public_key(client, conn, clients[0]->nickname,
+				   SILC_SOCKET_TYPE_CLIENT,
+				   pk, pk_len, SILC_SKE_PK_TYPE_SILC,
+				   silcpurple_add_buddy_save, r);
+	silc_free(pk);
+}
+
+static void
+silcpurple_add_buddy_i(PurpleConnection *gc, PurpleBuddy *b, gboolean init)
+{
+	SilcPurple sg = gc->proto_data;
+	SilcClient client = sg->client;
+	SilcClientConnection conn = sg->conn;
+	SilcPurpleBuddyRes r;
+	SilcBuffer attrs;
+	const char *filename, *name = b->name;
+
+	r = silc_calloc(1, sizeof(*r));
+	if (!r)
+		return;
+	r->client = client;
+	r->conn = conn;
+	r->b = b;
+	r->init = init;
+
+	/* See if we have this buddy's public key.  If we do use that
+	   to search the details. */
+	filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key");
+	if (filename) {
+		SilcPublicKey public_key;
+		SilcAttributeObjPk userpk;
+
+		if (!silc_pkcs_load_public_key(filename, &public_key,
+					       SILC_PKCS_FILE_PEM) &&
+		    !silc_pkcs_load_public_key(filename, &public_key,
+					       SILC_PKCS_FILE_BIN))
+			return;
+
+		/* Get all attributes, and use the public key to search user */
+		name = NULL;
+		attrs = silc_client_attributes_request(SILC_ATTRIBUTE_USER_INFO,
+						       SILC_ATTRIBUTE_SERVICE,
+						       SILC_ATTRIBUTE_STATUS_MOOD,
+						       SILC_ATTRIBUTE_STATUS_FREETEXT,
+						       SILC_ATTRIBUTE_STATUS_MESSAGE,
+						       SILC_ATTRIBUTE_PREFERRED_LANGUAGE,
+						       SILC_ATTRIBUTE_PREFERRED_CONTACT,
+						       SILC_ATTRIBUTE_TIMEZONE,
+						       SILC_ATTRIBUTE_GEOLOCATION,
+#ifdef SILC_ATTRIBUTE_USER_ICON
+						       SILC_ATTRIBUTE_USER_ICON,
+#endif
+						       SILC_ATTRIBUTE_DEVICE_INFO, 0);
+		userpk.type = "silc-rsa";
+		userpk.data = silc_pkcs_public_key_encode(public_key, &userpk.data_len);
+		attrs = silc_attribute_payload_encode(attrs,
+						      SILC_ATTRIBUTE_USER_PUBLIC_KEY,
+						      SILC_ATTRIBUTE_FLAG_VALID,
+						      &userpk, sizeof(userpk));
+		silc_free(userpk.data);
+		silc_pkcs_public_key_free(public_key);
+		r->pubkey_search = TRUE;
+	} else {
+		/* Get all attributes */
+		attrs = silc_client_attributes_request(0);
+	}
+
+	/* Resolve */
+	silc_client_get_clients_whois(client, conn, name, NULL, attrs,
+				      silcpurple_add_buddy_resolved, r);
+	silc_buffer_free(attrs);
+}
+
+void silcpurple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
+{
+	silcpurple_add_buddy_i(gc, buddy, FALSE);
+}
+
+void silcpurple_send_buddylist(PurpleConnection *gc)
+{
+	PurpleBuddyList *blist;
+	PurpleBlistNode *gnode, *cnode, *bnode;
+	PurpleBuddy *buddy;
+	PurpleAccount *account;
+
+	account = purple_connection_get_account(gc);
+
+	if ((blist = purple_get_blist()) != NULL)
+	{
+		for (gnode = blist->root; gnode != NULL; gnode = gnode->next)
+		{
+			if (!PURPLE_BLIST_NODE_IS_GROUP(gnode))
+				continue;
+			for (cnode = gnode->child; cnode != NULL; cnode = cnode->next)
+			{
+				if (!PURPLE_BLIST_NODE_IS_CONTACT(cnode))
+					continue;
+				for (bnode = cnode->child; bnode != NULL; bnode = bnode->next)
+				{
+					if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode))
+						continue;
+					buddy = (PurpleBuddy *)bnode;
+					if (purple_buddy_get_account(buddy) == account)
+						silcpurple_add_buddy_i(gc, buddy, TRUE);
+				}
+			}
+		}
+	}
+}
+
+void silcpurple_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
+			   PurpleGroup *group)
+{
+	silc_free(buddy->proto_data);
+}
+
+void silcpurple_idle_set(PurpleConnection *gc, int idle)
+
+{
+	SilcPurple sg = gc->proto_data;
+	SilcClient client = sg->client;
+	SilcClientConnection conn = sg->conn;
+	SilcAttributeObjService service;
+	const char *server;
+	int port;
+
+	server = purple_account_get_string(sg->account, "server",
+					 "silc.silcnet.org");
+	port = purple_account_get_int(sg->account, "port", 706),
+
+	memset(&service, 0, sizeof(service));
+	silc_client_attribute_del(client, conn,
+				  SILC_ATTRIBUTE_SERVICE, NULL);
+	service.port = port;
+	g_snprintf(service.address, sizeof(service.address), "%s", server);
+	service.idle = idle;
+	silc_client_attribute_add(client, conn, SILC_ATTRIBUTE_SERVICE,
+				  &service, sizeof(service));
+}
+
+char *silcpurple_status_text(PurpleBuddy *b)
+{
+	SilcPurple sg = b->account->gc->proto_data;
+	SilcClient client = sg->client;
+	SilcClientConnection conn = sg->conn;
+	SilcClientID *client_id = b->proto_data;
+	SilcClientEntry client_entry;
+	SilcAttributePayload attr;
+	SilcAttributeMood mood = 0;
+
+	/* Get the client entry. */
+	client_entry = silc_client_get_client_by_id(client, conn, client_id);
+	if (!client_entry)
+		return NULL;
+
+	/* If user is online, we show the mood status, if available.
+	   If user is offline or away that status is indicated. */
+
+	if (client_entry->mode & SILC_UMODE_DETACHED)
+		return g_strdup(_("Detached"));
+	if (client_entry->mode & SILC_UMODE_GONE)
+		return g_strdup(_("Away"));
+	if (client_entry->mode & SILC_UMODE_INDISPOSED)
+		return g_strdup(_("Indisposed"));
+	if (client_entry->mode & SILC_UMODE_BUSY)
+		return g_strdup(_("Busy"));
+	if (client_entry->mode & SILC_UMODE_PAGE)
+		return g_strdup(_("Wake Me Up"));
+	if (client_entry->mode & SILC_UMODE_HYPER)
+		return g_strdup(_("Hyper Active"));
+	if (client_entry->mode & SILC_UMODE_ROBOT)
+		return g_strdup(_("Robot"));
+
+	attr = silcpurple_get_attr(client_entry->attrs, SILC_ATTRIBUTE_STATUS_MOOD);
+	if (attr && silc_attribute_get_object(attr, &mood, sizeof(mood))) {
+		/* The mood is a bit mask, so we could show multiple moods,
+		   but let's show only one for now. */
+		if (mood & SILC_ATTRIBUTE_MOOD_HAPPY)
+			return g_strdup(_("Happy"));
+		if (mood & SILC_ATTRIBUTE_MOOD_SAD)
+			return g_strdup(_("Sad"));
+		if (mood & SILC_ATTRIBUTE_MOOD_ANGRY)
+			return g_strdup(_("Angry"));
+		if (mood & SILC_ATTRIBUTE_MOOD_JEALOUS)
+			return g_strdup(_("Jealous"));
+		if (mood & SILC_ATTRIBUTE_MOOD_ASHAMED)
+			return g_strdup(_("Ashamed"));
+		if (mood & SILC_ATTRIBUTE_MOOD_INVINCIBLE)
+			return g_strdup(_("Invincible"));
+		if (mood & SILC_ATTRIBUTE_MOOD_INLOVE)
+			return g_strdup(_("In Love"));
+		if (mood & SILC_ATTRIBUTE_MOOD_SLEEPY)
+			return g_strdup(_("Sleepy"));
+		if (mood & SILC_ATTRIBUTE_MOOD_BORED)
+			return g_strdup(_("Bored"));
+		if (mood & SILC_ATTRIBUTE_MOOD_EXCITED)
+			return g_strdup(_("Excited"));
+		if (mood & SILC_ATTRIBUTE_MOOD_ANXIOUS)
+			return g_strdup(_("Anxious"));
+	}
+
+	return NULL;
+}
+
+void silcpurple_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full)
+{
+	SilcPurple sg = b->account->gc->proto_data;
+	SilcClient client = sg->client;
+	SilcClientConnection conn = sg->conn;
+	SilcClientID *client_id = b->proto_data;
+	SilcClientEntry client_entry;
+	char *moodstr, *statusstr, *contactstr, *langstr, *devicestr, *tzstr, *geostr;
+	char tmp[256];
+
+	/* Get the client entry. */
+	client_entry = silc_client_get_client_by_id(client, conn, client_id);
+	if (!client_entry)
+		return;
+
+	if (client_entry->nickname)
+		purple_notify_user_info_add_pair(user_info, _("Nickname"),
+					       client_entry->nickname);
+	if (client_entry->username && client_entry->hostname) {
+		g_snprintf(tmp, sizeof(tmp), "%s@%s", client_entry->username, client_entry->hostname);
+		purple_notify_user_info_add_pair(user_info, _("Username"), tmp);
+	}
+	if (client_entry->mode) {
+		memset(tmp, 0, sizeof(tmp));
+		silcpurple_get_umode_string(client_entry->mode,
+					  tmp, sizeof(tmp) - strlen(tmp));
+		purple_notify_user_info_add_pair(user_info, _("User Modes"), tmp);
+	}
+
+	silcpurple_parse_attrs(client_entry->attrs, &moodstr, &statusstr, &contactstr, &langstr, &devicestr, &tzstr, &geostr);
+
+	if (statusstr) {
+		purple_notify_user_info_add_pair(user_info, _("Message"), statusstr);
+		g_free(statusstr);
+	}
+
+	if (full) {
+		if (moodstr) {
+			purple_notify_user_info_add_pair(user_info, _("Mood"), moodstr);
+			g_free(moodstr);
+		}
+
+		if (contactstr) {
+			purple_notify_user_info_add_pair(user_info, _("Preferred Contact"), contactstr);
+			g_free(contactstr);
+		}
+
+		if (langstr) {
+			purple_notify_user_info_add_pair(user_info, _("Preferred Language"), langstr);
+			g_free(langstr);
+		}
+
+		if (devicestr) {
+			purple_notify_user_info_add_pair(user_info, _("Device"), devicestr);
+			g_free(devicestr);
+		}
+
+		if (tzstr) {
+			purple_notify_user_info_add_pair(user_info, _("Timezone"), tzstr);
+			g_free(tzstr);
+		}
+
+		if (geostr) {
+			purple_notify_user_info_add_pair(user_info, _("Geolocation"), geostr);
+			g_free(geostr);
+		}
+	}
+}
+
+static void
+silcpurple_buddy_kill(PurpleBlistNode *node, gpointer data)
+{
+	PurpleBuddy *b;
+	PurpleConnection *gc;
+	SilcPurple sg;
+
+	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+
+	b = (PurpleBuddy *) node;
+	gc = purple_account_get_connection(b->account);
+	sg = gc->proto_data;
+
+	/* Call KILL */
+	silc_client_command_call(sg->client, sg->conn, NULL, "KILL",
+				 b->name, "Killed by operator", NULL);
+}
+
+typedef struct {
+	SilcPurple sg;
+	SilcClientEntry client_entry;
+} *SilcPurpleBuddyWb;
+
+static void
+silcpurple_buddy_wb(PurpleBlistNode *node, gpointer data)
+{
+	SilcPurpleBuddyWb wb = data;
+	silcpurple_wb_init(wb->sg, wb->client_entry);
+	silc_free(wb);
+}
+
+GList *silcpurple_buddy_menu(PurpleBuddy *buddy)
+{
+	PurpleConnection *gc = purple_account_get_connection(buddy->account);
+	SilcPurple sg = gc->proto_data;
+	SilcClientConnection conn = sg->conn;
+	const char *pkfile = NULL;
+	SilcClientEntry client_entry = NULL;
+	PurpleMenuAction *act;
+	GList *m = NULL;
+	SilcPurpleBuddyWb wb;
+
+	pkfile = purple_blist_node_get_string((PurpleBlistNode *) buddy, "public-key");
+	client_entry = silc_client_get_client_by_id(sg->client,
+						    sg->conn,
+						    buddy->proto_data);
+
+	if (client_entry && client_entry->send_key) {
+		act = purple_menu_action_new(_("Reset IM Key"),
+		                           PURPLE_CALLBACK(silcpurple_buddy_resetkey),
+		                           NULL, NULL);
+		m = g_list_append(m, act);
+
+	} else {
+		act = purple_menu_action_new(_("IM with Key Exchange"),
+		                           PURPLE_CALLBACK(silcpurple_buddy_keyagr),
+		                           NULL, NULL);
+		m = g_list_append(m, act);
+
+		act = purple_menu_action_new(_("IM with Password"),
+		                           PURPLE_CALLBACK(silcpurple_buddy_privkey_menu),
+		                           NULL, NULL);
+		m = g_list_append(m, act);
+	}
+
+	if (pkfile) {
+		act = purple_menu_action_new(_("Show Public Key"),
+		                           PURPLE_CALLBACK(silcpurple_buddy_showkey),
+		                           NULL, NULL);
+		m = g_list_append(m, act);
+
+	} else {
+		act = purple_menu_action_new(_("Get Public Key..."),
+		                           PURPLE_CALLBACK(silcpurple_buddy_getkey_menu),
+		                           NULL, NULL);
+		m = g_list_append(m, act);
+	}
+
+	if (conn && conn->local_entry->mode & SILC_UMODE_ROUTER_OPERATOR) {
+		act = purple_menu_action_new(_("Kill User"),
+		                           PURPLE_CALLBACK(silcpurple_buddy_kill),
+		                           NULL, NULL);
+		m = g_list_append(m, act);
+	}
+
+	if (client_entry) {
+		wb = silc_calloc(1, sizeof(*wb));
+		wb->sg = sg;
+		wb->client_entry = client_entry;
+		act = purple_menu_action_new(_("Draw On Whiteboard"),
+		                           PURPLE_CALLBACK(silcpurple_buddy_wb),
+		                           (void *)wb, NULL);
+		m = g_list_append(m, act);
+	}
+	return m;
+}
+
+#ifdef SILC_ATTRIBUTE_USER_ICON
+void silcpurple_buddy_set_icon(PurpleConnection *gc, PurpleStoredImage *img)
+{
+	SilcPurple sg = gc->proto_data;
+	SilcClient client = sg->client;
+	SilcClientConnection conn = sg->conn;
+	SilcMime mime;
+	char type[32];
+	unsigned char *icon;
+	const char *t;
+	SilcAttributeObjMime obj;
+
+	/* Remove */
+	if (!img) {
+		silc_client_attribute_del(client, conn,
+					  SILC_ATTRIBUTE_USER_ICON, NULL);
+		return;
+	}
+
+	/* Add */
+	mime = silc_mime_alloc();
+	if (!mime)
+		return;
+
+	t = purple_imgstore_get_extension(img);
+	if (!t || !strcmp(t, "icon")) {
+		silc_mime_free(mime);
+		return;
+	}
+	if (!strcmp(t, "jpg"))
+		t = "jpeg";
+	g_snprintf(type, sizeof(type), "image/%s", t);
+	silc_mime_add_field(mime, "Content-Type", type);
+	silc_mime_add_data(mime, purple_imgstore_get_data(img), purple_imgstore_get_size(img));
+
+	obj.mime = icon = silc_mime_encode(mime, &obj.mime_len);
+	if (obj.mime)
+		silc_client_attribute_add(client, conn, 
+					  SILC_ATTRIBUTE_USER_ICON, &obj, sizeof(obj));
+
+	silc_free(icon);
+	silc_mime_free(mime);
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/silc10/chat.c	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,1456 @@
+/*
+
+  silcpurple_chat.c
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2004 Pekka Riikonen
+
+  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; version 2 of the License.
+
+  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.
+
+*/
+
+#include "silcincludes.h"
+#include "silcclient.h"
+#include "silcpurple.h"
+#include "wb.h"
+
+/***************************** Channel Routines ******************************/
+
+GList *silcpurple_chat_info(PurpleConnection *gc)
+{
+	GList *ci = NULL;
+	struct proto_chat_entry *pce;
+
+	pce = g_new0(struct proto_chat_entry, 1);
+	pce->label = _("_Channel:");
+	pce->identifier = "channel";
+	pce->required = TRUE;
+	ci = g_list_append(ci, pce);
+
+	pce = g_new0(struct proto_chat_entry, 1);
+	pce->label = _("_Passphrase:");
+	pce->identifier = "passphrase";
+	pce->secret = TRUE;
+	ci = g_list_append(ci, pce);
+
+	return ci;
+}
+
+GHashTable *silcpurple_chat_info_defaults(PurpleConnection *gc, const char *chat_name)
+{
+	GHashTable *defaults;
+
+	defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
+
+	if (chat_name != NULL)
+		g_hash_table_insert(defaults, "channel", g_strdup(chat_name));
+
+	return defaults;
+}
+
+static void
+silcpurple_chat_getinfo(PurpleConnection *gc, GHashTable *components);
+
+static void
+silcpurple_chat_getinfo_res(SilcClient client,
+			  SilcClientConnection conn,
+			  SilcChannelEntry *channels,
+			  SilcUInt32 channels_count,
+			  void *context)
+{
+	GHashTable *components = context;
+	PurpleConnection *gc = client->application;
+	const char *chname;
+	char tmp[256];
+
+	chname = g_hash_table_lookup(components, "channel");
+	if (!chname)
+		return;
+
+	if (!channels) {
+		g_snprintf(tmp, sizeof(tmp),
+			   _("Channel %s does not exist in the network"), chname);
+		purple_notify_error(gc, _("Channel Information"),
+				  _("Cannot get channel information"), tmp);
+		return;
+	}
+
+	silcpurple_chat_getinfo(gc, components);
+}
+
+
+static void
+silcpurple_chat_getinfo(PurpleConnection *gc, GHashTable *components)
+{
+	SilcPurple sg = gc->proto_data;
+	const char *chname;
+	char *buf, tmp[256], *tmp2;
+	GString *s;
+	SilcChannelEntry channel;
+	SilcHashTableList htl;
+	SilcChannelUser chu;
+
+	if (!components)
+		return;
+
+	chname = g_hash_table_lookup(components, "channel");
+	if (!chname)
+		return;
+	channel = silc_client_get_channel(sg->client, sg->conn,
+					  (char *)chname);
+	if (!channel) {
+		silc_client_get_channel_resolve(sg->client, sg->conn,
+						(char *)chname,
+						silcpurple_chat_getinfo_res,
+						components);
+		return;
+	}
+
+	s = g_string_new("");
+	tmp2 = g_markup_escape_text(channel->channel_name, -1);
+	g_string_append_printf(s, _("<b>Channel Name:</b> %s"), tmp2);
+	g_free(tmp2);
+	if (channel->user_list && silc_hash_table_count(channel->user_list))
+		g_string_append_printf(s, _("<br><b>User Count:</b> %d"),
+				       (int)silc_hash_table_count(channel->user_list));
+
+	silc_hash_table_list(channel->user_list, &htl);
+	while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
+		if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) {
+			tmp2 = g_markup_escape_text(chu->client->nickname, -1);
+			g_string_append_printf(s, _("<br><b>Channel Founder:</b> %s"),
+					       tmp2);
+			g_free(tmp2);
+			break;
+		}
+	}
+	silc_hash_table_list_reset(&htl);
+
+	if (channel->channel_key)
+		g_string_append_printf(s, _("<br><b>Channel Cipher:</b> %s"),
+				       silc_cipher_get_name(channel->channel_key));
+	if (channel->hmac)
+		/* Definition of HMAC: http://en.wikipedia.org/wiki/HMAC */
+		g_string_append_printf(s, _("<br><b>Channel HMAC:</b> %s"),
+				       silc_hmac_get_name(channel->hmac));
+
+	if (channel->topic) {
+		tmp2 = g_markup_escape_text(channel->topic, -1);
+		g_string_append_printf(s, _("<br><b>Channel Topic:</b><br>%s"), tmp2);
+		g_free(tmp2);
+	}
+
+	if (channel->mode) {
+		g_string_append_printf(s, _("<br><b>Channel Modes:</b> "));
+		silcpurple_get_chmode_string(channel->mode, tmp, sizeof(tmp));
+		g_string_append(s, tmp);
+	}
+
+	if (channel->founder_key) {
+		char *fingerprint, *babbleprint;
+		unsigned char *pk;
+		SilcUInt32 pk_len;
+		pk = silc_pkcs_public_key_encode(channel->founder_key, &pk_len);
+		fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
+		babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
+
+		g_string_append_printf(s, _("<br><b>Founder Key Fingerprint:</b><br>%s"), fingerprint);
+		g_string_append_printf(s, _("<br><b>Founder Key Babbleprint:</b><br>%s"), babbleprint);
+
+		silc_free(fingerprint);
+		silc_free(babbleprint);
+		silc_free(pk);
+	}
+
+	buf = g_string_free(s, FALSE);
+	purple_notify_formatted(gc, NULL, _("Channel Information"), NULL, buf, NULL, NULL);
+	g_free(buf);
+}
+
+
+static void
+silcpurple_chat_getinfo_menu(PurpleBlistNode *node, gpointer data)
+{
+	PurpleChat *chat = (PurpleChat *)node;
+	silcpurple_chat_getinfo(chat->account->gc, chat->components);
+}
+
+
+#if 0   /* XXX For now these are not implemented.  We need better
+	   listview dialog from Purple for these. */
+/************************** Channel Invite List ******************************/
+
+static void
+silcpurple_chat_invitelist(PurpleBlistNode *node, gpointer data);
+{
+
+}
+
+
+/**************************** Channel Ban List *******************************/
+
+static void
+silcpurple_chat_banlist(PurpleBlistNode *node, gpointer data);
+{
+
+}
+#endif
+
+
+/************************* Channel Authentication ****************************/
+
+typedef struct {
+	SilcPurple sg;
+	SilcChannelEntry channel;
+	PurpleChat *c;
+	SilcBuffer pubkeys;
+} *SilcPurpleChauth;
+
+static void
+silcpurple_chat_chpk_add(void *user_data, const char *name)
+{
+	SilcPurpleChauth sgc = (SilcPurpleChauth)user_data;
+	SilcPurple sg = sgc->sg;
+	SilcClient client = sg->client;
+	SilcClientConnection conn = sg->conn;
+	SilcPublicKey public_key;
+	SilcBuffer chpks, pk, chidp;
+	unsigned char mode[4];
+	SilcUInt32 m;
+
+	/* Load the public key */
+	if (!silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_PEM) &&
+	    !silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_BIN)) {
+		silcpurple_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys);
+		silc_buffer_free(sgc->pubkeys);
+		silc_free(sgc);
+		purple_notify_error(client->application,
+				  _("Add Channel Public Key"),
+				  _("Could not load public key"), NULL);
+		return;
+	}
+
+	pk = silc_pkcs_public_key_payload_encode(public_key);
+	chpks = silc_buffer_alloc_size(2);
+	SILC_PUT16_MSB(1, chpks->head);
+	chpks = silc_argument_payload_encode_one(chpks, pk->data,
+						 pk->len, 0x00);
+	silc_buffer_free(pk);
+
+	m = sgc->channel->mode;
+	m |= SILC_CHANNEL_MODE_CHANNEL_AUTH;
+
+	/* Send CMODE */
+	SILC_PUT32_MSB(m, mode);
+	chidp = silc_id_payload_encode(sgc->channel->id, SILC_ID_CHANNEL);
+	silc_client_command_send(client, conn, SILC_COMMAND_CMODE,
+				 ++conn->cmd_ident, 3,
+				 1, chidp->data, chidp->len,
+				 2, mode, sizeof(mode),
+				 9, chpks->data, chpks->len);
+	silc_buffer_free(chpks);
+	silc_buffer_free(chidp);
+	silc_buffer_free(sgc->pubkeys);
+	silc_free(sgc);
+}
+
+static void
+silcpurple_chat_chpk_cancel(void *user_data, const char *name)
+{
+	SilcPurpleChauth sgc = (SilcPurpleChauth)user_data;
+	silcpurple_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys);
+	silc_buffer_free(sgc->pubkeys);
+	silc_free(sgc);
+}
+
+static void
+silcpurple_chat_chpk_cb(SilcPurpleChauth sgc, PurpleRequestFields *fields)
+{
+	SilcPurple sg = sgc->sg;
+	SilcClient client = sg->client;
+	SilcClientConnection conn = sg->conn;
+	PurpleRequestField *f;
+	const GList *list;
+	SilcPublicKey public_key;
+	SilcBuffer chpks, pk, chidp;
+	SilcUInt16 c = 0, ct;
+	unsigned char mode[4];
+	SilcUInt32 m;
+
+	f = purple_request_fields_get_field(fields, "list");
+	if (!purple_request_field_list_get_selected(f)) {
+		/* Add new public key */
+		purple_request_file(sg->gc, _("Open Public Key..."), NULL, FALSE,
+				  G_CALLBACK(silcpurple_chat_chpk_add),
+				  G_CALLBACK(silcpurple_chat_chpk_cancel),
+				  purple_connection_get_account(sg->gc), NULL, NULL, sgc);
+		return;
+	}
+
+	list = purple_request_field_list_get_items(f);
+	chpks = silc_buffer_alloc_size(2);
+
+	for (ct = 0; list; list = list->next, ct++) {
+		public_key = purple_request_field_list_get_data(f, list->data);
+		if (purple_request_field_list_is_selected(f, list->data)) {
+			/* Delete this public key */
+			pk = silc_pkcs_public_key_payload_encode(public_key);
+			chpks = silc_argument_payload_encode_one(chpks, pk->data,
+								 pk->len, 0x01);
+			silc_buffer_free(pk);
+			c++;
+		}
+		silc_pkcs_public_key_free(public_key);
+	}
+	if (!c) {
+		silc_buffer_free(chpks);
+		return;
+	}
+	SILC_PUT16_MSB(c, chpks->head);
+
+	m = sgc->channel->mode;
+	if (ct == c)
+		m &= ~SILC_CHANNEL_MODE_CHANNEL_AUTH;
+
+	/* Send CMODE */
+	SILC_PUT32_MSB(m, mode);
+	chidp = silc_id_payload_encode(sgc->channel->id, SILC_ID_CHANNEL);
+	silc_client_command_send(client, conn, SILC_COMMAND_CMODE,
+				 ++conn->cmd_ident, 3,
+				 1, chidp->data, chidp->len,
+				 2, mode, sizeof(mode),
+				 9, chpks->data, chpks->len);
+	silc_buffer_free(chpks);
+	silc_buffer_free(chidp);
+	silc_buffer_free(sgc->pubkeys);
+	silc_free(sgc);
+}
+
+static void
+silcpurple_chat_chauth_ok(SilcPurpleChauth sgc, PurpleRequestFields *fields)
+{
+	SilcPurple sg = sgc->sg;
+	PurpleRequestField *f;
+	const char *curpass, *val;
+	int set;
+
+	f = purple_request_fields_get_field(fields, "passphrase");
+	val = purple_request_field_string_get_value(f);
+	curpass = purple_blist_node_get_string((PurpleBlistNode *)sgc->c, "passphrase");
+
+	if (!val && curpass)
+		set = 0;
+	else if (val && !curpass)
+		set = 1;
+	else if (val && curpass && strcmp(val, curpass))
+		set = 1;
+	else
+		set = -1;
+
+	if (set == 1) {
+		silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
+					 sgc->channel->channel_name, "+a", val, NULL);
+		purple_blist_node_set_string((PurpleBlistNode *)sgc->c, "passphrase", val);
+	} else if (set == 0) {
+		silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
+					 sgc->channel->channel_name, "-a", NULL);
+		purple_blist_node_remove_setting((PurpleBlistNode *)sgc->c, "passphrase");
+	}
+
+	silc_buffer_free(sgc->pubkeys);
+	silc_free(sgc);
+}
+
+void silcpurple_chat_chauth_show(SilcPurple sg, SilcChannelEntry channel,
+			       SilcBuffer channel_pubkeys)
+{
+	SilcUInt16 argc;
+	SilcArgumentPayload chpks;
+	unsigned char *pk;
+	SilcUInt32 pk_len, type;
+	char *fingerprint, *babbleprint;
+	SilcPublicKey pubkey;
+	SilcPublicKeyIdentifier ident;
+	char tmp2[1024], t[512];
+	PurpleRequestFields *fields;
+	PurpleRequestFieldGroup *g;
+	PurpleRequestField *f;
+	SilcPurpleChauth sgc;
+	const char *curpass = NULL;
+
+	sgc = silc_calloc(1, sizeof(*sgc));
+	if (!sgc)
+		return;
+	sgc->sg = sg;
+	sgc->channel = channel;
+
+	fields = purple_request_fields_new();
+
+	if (sgc->c)
+	  curpass = purple_blist_node_get_string((PurpleBlistNode *)sgc->c, "passphrase");
+
+	g = purple_request_field_group_new(NULL);
+	f = purple_request_field_string_new("passphrase", _("Channel Passphrase"),
+					  curpass, FALSE);
+	purple_request_field_string_set_masked(f, TRUE);
+	purple_request_field_group_add_field(g, f);
+	purple_request_fields_add_group(fields, g);
+
+	g = purple_request_field_group_new(NULL);
+	f = purple_request_field_label_new("l1", _("Channel Public Keys List"));
+	purple_request_field_group_add_field(g, f);
+	purple_request_fields_add_group(fields, g);
+
+	g_snprintf(t, sizeof(t),
+		   _("Channel authentication is used to secure the channel from "
+		     "unauthorized access. The authentication may be based on "
+		     "passphrase and digital signatures. If passphrase is set, it "
+		     "is required to be able to join. If channel public keys are set "
+		     "then only users whose public keys are listed are able to join."));
+
+	if (!channel_pubkeys) {
+		f = purple_request_field_list_new("list", NULL);
+		purple_request_field_group_add_field(g, f);
+		purple_request_fields(sg->gc, _("Channel Authentication"),
+				    _("Channel Authentication"), t, fields,
+				    _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb),
+				    _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok),
+					purple_connection_get_account(sg->gc), NULL, NULL, sgc);
+		return;
+	}
+	sgc->pubkeys = silc_buffer_copy(channel_pubkeys);
+
+	g = purple_request_field_group_new(NULL);
+	f = purple_request_field_list_new("list", NULL);
+	purple_request_field_group_add_field(g, f);
+	purple_request_fields_add_group(fields, g);
+
+	SILC_GET16_MSB(argc, channel_pubkeys->data);
+	chpks = silc_argument_payload_parse(channel_pubkeys->data + 2,
+					    channel_pubkeys->len - 2, argc);
+	if (!chpks)
+		return;
+
+	pk = silc_argument_get_first_arg(chpks, &type, &pk_len);
+	while (pk) {
+		fingerprint = silc_hash_fingerprint(NULL, pk + 4, pk_len - 4);
+		babbleprint = silc_hash_babbleprint(NULL, pk + 4, pk_len - 4);
+		silc_pkcs_public_key_payload_decode(pk, pk_len, &pubkey);
+		ident = silc_pkcs_decode_identifier(pubkey->identifier);
+
+		g_snprintf(tmp2, sizeof(tmp2), "%s\n  %s\n  %s",
+			   ident->realname ? ident->realname : ident->username ?
+			   ident->username : "", fingerprint, babbleprint);
+		purple_request_field_list_add(f, tmp2, pubkey);
+
+		silc_free(fingerprint);
+		silc_free(babbleprint);
+		silc_pkcs_free_identifier(ident);
+		pk = silc_argument_get_next_arg(chpks, &type, &pk_len);
+	}
+
+	purple_request_field_list_set_multi_select(f, FALSE);
+	purple_request_fields(sg->gc, _("Channel Authentication"),
+			    _("Channel Authentication"), t, fields,
+			    _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb),
+			    _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok),
+				purple_connection_get_account(sg->gc), NULL, NULL, sgc);
+
+	silc_argument_payload_free(chpks);
+}
+
+static void
+silcpurple_chat_chauth(PurpleBlistNode *node, gpointer data)
+{
+	PurpleChat *chat;
+	PurpleConnection *gc;
+	SilcPurple sg;
+
+	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
+
+	chat = (PurpleChat *) node;
+	gc = purple_account_get_connection(chat->account);
+	sg = gc->proto_data;
+
+	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
+				 g_hash_table_lookup(chat->components, "channel"),
+				 "+C", NULL);
+}
+
+
+/************************** Channel Private Groups **************************/
+
+/* Private groups are "virtual" channels.  They are groups inside a channel.
+   This is implemented by using channel private keys.  By knowing a channel
+   private key user becomes part of that group and is able to talk on that
+   group.  Other users, on the same channel, won't be able to see the
+   messages of that group.  It is possible to have multiple groups inside
+   a channel - and thus having multiple private keys on the channel. */
+
+typedef struct {
+	SilcPurple sg;
+	PurpleChat *c;
+	const char *channel;
+} *SilcPurpleCharPrv;
+
+static void
+silcpurple_chat_prv_add(SilcPurpleCharPrv p, PurpleRequestFields *fields)
+{
+	SilcPurple sg = p->sg;
+	char tmp[512];
+	PurpleRequestField *f;
+	const char *name, *passphrase, *alias;
+	GHashTable *comp;
+	PurpleGroup *g;
+	PurpleChat *cn;
+
+	f = purple_request_fields_get_field(fields, "name");
+	name = purple_request_field_string_get_value(f);
+	if (!name) {
+		silc_free(p);
+		return;
+	}
+	f = purple_request_fields_get_field(fields, "passphrase");
+	passphrase = purple_request_field_string_get_value(f);
+	f = purple_request_fields_get_field(fields, "alias");
+	alias = purple_request_field_string_get_value(f);
+
+	/* Add private group to buddy list */
+	g_snprintf(tmp, sizeof(tmp), "%s [Private Group]", name);
+	comp = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+	g_hash_table_replace(comp, g_strdup("channel"), g_strdup(tmp));
+	g_hash_table_replace(comp, g_strdup("passphrase"), g_strdup(passphrase));
+
+	cn = purple_chat_new(sg->account, alias, comp);
+	g = (PurpleGroup *)p->c->node.parent;
+	purple_blist_add_chat(cn, g, (PurpleBlistNode *)p->c);
+
+	/* Associate to a real channel */
+	purple_blist_node_set_string((PurpleBlistNode *)cn, "parentch", p->channel);
+
+	/* Join the group */
+	silcpurple_chat_join(sg->gc, comp);
+
+	silc_free(p);
+}
+
+static void
+silcpurple_chat_prv_cancel(SilcPurpleCharPrv p, PurpleRequestFields *fields)
+{
+	silc_free(p);
+}
+
+static void
+silcpurple_chat_prv(PurpleBlistNode *node, gpointer data)
+{
+	PurpleChat *chat;
+	PurpleConnection *gc;
+	SilcPurple sg;
+
+	SilcPurpleCharPrv p;
+	PurpleRequestFields *fields;
+	PurpleRequestFieldGroup *g;
+	PurpleRequestField *f;
+	char tmp[512];
+
+	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
+
+	chat = (PurpleChat *) node;
+	gc = purple_account_get_connection(chat->account);
+	sg = gc->proto_data;
+
+	p = silc_calloc(1, sizeof(*p));
+	if (!p)
+		return;
+	p->sg = sg;
+
+	p->channel = g_hash_table_lookup(chat->components, "channel");
+	p->c = purple_blist_find_chat(sg->account, p->channel);
+
+	fields = purple_request_fields_new();
+
+	g = purple_request_field_group_new(NULL);
+	f = purple_request_field_string_new("name", _("Group Name"),
+					  NULL, FALSE);
+	purple_request_field_group_add_field(g, f);
+
+	f = purple_request_field_string_new("passphrase", _("Passphrase"),
+					  NULL, FALSE);
+	purple_request_field_string_set_masked(f, TRUE);
+	purple_request_field_group_add_field(g, f);
+
+	f = purple_request_field_string_new("alias", _("Alias"),
+					  NULL, FALSE);
+	purple_request_field_group_add_field(g, f);
+	purple_request_fields_add_group(fields, g);
+
+	g_snprintf(tmp, sizeof(tmp),
+		   _("Please enter the %s channel private group name and passphrase."),
+		   p->channel);
+	purple_request_fields(gc, _("Add Channel Private Group"), NULL, tmp, fields,
+			    _("Add"), G_CALLBACK(silcpurple_chat_prv_add),
+			    _("Cancel"), G_CALLBACK(silcpurple_chat_prv_cancel),
+				purple_connection_get_account(gc), NULL, NULL, p);
+}
+
+
+/****************************** Channel Modes ********************************/
+
+static void
+silcpurple_chat_permanent_reset(PurpleBlistNode *node, gpointer data)
+{
+	PurpleChat *chat;
+	PurpleConnection *gc;
+	SilcPurple sg;
+
+	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
+
+	chat = (PurpleChat *) node;
+	gc = purple_account_get_connection(chat->account);
+	sg = gc->proto_data;
+
+	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
+				 g_hash_table_lookup(chat->components, "channel"),
+				 "-f", NULL);
+}
+
+static void
+silcpurple_chat_permanent(PurpleBlistNode *node, gpointer data)
+{
+	PurpleChat *chat;
+	PurpleConnection *gc;
+	SilcPurple sg;
+	const char *channel;
+
+	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
+
+	chat = (PurpleChat *) node;
+	gc = purple_account_get_connection(chat->account);
+	sg = gc->proto_data;
+
+	if (!sg->conn)
+		return;
+
+	/* XXX we should have ability to define which founder
+	   key to use.  Now we use the user's own public key
+	   (default key). */
+
+	/* Call CMODE */
+	channel = g_hash_table_lookup(chat->components, "channel");
+	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", channel,
+				 "+f", NULL);
+}
+
+typedef struct {
+	SilcPurple sg;
+	const char *channel;
+} *SilcPurpleChatInput;
+
+static void
+silcpurple_chat_ulimit_cb(SilcPurpleChatInput s, const char *limit)
+{
+	SilcChannelEntry channel;
+	int ulimit = 0;
+
+	channel = silc_client_get_channel(s->sg->client, s->sg->conn,
+					  (char *)s->channel);
+	if (!channel)
+		return;
+	if (limit)
+		ulimit = atoi(limit);
+
+	if (!limit || !(*limit) || *limit == '0') {
+		if (limit && ulimit == channel->user_limit) {
+			silc_free(s);
+			return;
+		}
+		silc_client_command_call(s->sg->client, s->sg->conn, NULL, "CMODE",
+					 s->channel, "-l", NULL);
+
+		silc_free(s);
+		return;
+	}
+
+	if (ulimit == channel->user_limit) {
+		silc_free(s);
+		return;
+	}
+
+	/* Call CMODE */
+	silc_client_command_call(s->sg->client, s->sg->conn, NULL, "CMODE",
+				 s->channel, "+l", limit, NULL);
+
+	silc_free(s);
+}
+
+static void
+silcpurple_chat_ulimit(PurpleBlistNode *node, gpointer data)
+{
+	PurpleChat *chat;
+	PurpleConnection *gc;
+	SilcPurple sg;
+
+	SilcPurpleChatInput s;
+	SilcChannelEntry channel;
+	const char *ch;
+	char tmp[32];
+
+	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
+
+	chat = (PurpleChat *) node;
+	gc = purple_account_get_connection(chat->account);
+	sg = gc->proto_data;
+
+	if (!sg->conn)
+		return;
+
+	ch = g_strdup(g_hash_table_lookup(chat->components, "channel"));
+	channel = silc_client_get_channel(sg->client, sg->conn, (char *)ch);
+	if (!channel)
+		return;
+
+	s = silc_calloc(1, sizeof(*s));
+	if (!s)
+		return;
+	s->channel = ch;
+	s->sg = sg;
+	g_snprintf(tmp, sizeof(tmp), "%d", (int)channel->user_limit);
+	purple_request_input(gc, _("User Limit"), NULL,
+			   _("Set user limit on channel. Set to zero to reset user limit."),
+			   tmp, FALSE, FALSE, NULL,
+			   _("OK"), G_CALLBACK(silcpurple_chat_ulimit_cb),
+			   _("Cancel"), G_CALLBACK(silcpurple_chat_ulimit_cb),
+			   purple_connection_get_account(gc), NULL, NULL, s);
+}
+
+static void
+silcpurple_chat_resettopic(PurpleBlistNode *node, gpointer data)
+{
+	PurpleChat *chat;
+	PurpleConnection *gc;
+	SilcPurple sg;
+
+	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
+
+	chat = (PurpleChat *) node;
+	gc = purple_account_get_connection(chat->account);
+	sg = gc->proto_data;
+
+	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
+				 g_hash_table_lookup(chat->components, "channel"),
+				 "-t", NULL);
+}
+
+static void
+silcpurple_chat_settopic(PurpleBlistNode *node, gpointer data)
+{
+	PurpleChat *chat;
+	PurpleConnection *gc;
+	SilcPurple sg;
+
+	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
+
+	chat = (PurpleChat *) node;
+	gc = purple_account_get_connection(chat->account);
+	sg = gc->proto_data;
+
+	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
+				 g_hash_table_lookup(chat->components, "channel"),
+				 "+t", NULL);
+}
+
+static void
+silcpurple_chat_resetprivate(PurpleBlistNode *node, gpointer data)
+{
+	PurpleChat *chat;
+	PurpleConnection *gc;
+	SilcPurple sg;
+
+	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
+
+	chat = (PurpleChat *) node;
+	gc = purple_account_get_connection(chat->account);
+	sg = gc->proto_data;
+
+	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
+				 g_hash_table_lookup(chat->components, "channel"),
+				 "-p", NULL);
+}
+
+static void
+silcpurple_chat_setprivate(PurpleBlistNode *node, gpointer data)
+{
+	PurpleChat *chat;
+	PurpleConnection *gc;
+	SilcPurple sg;
+
+	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
+
+	chat = (PurpleChat *) node;
+	gc = purple_account_get_connection(chat->account);
+	sg = gc->proto_data;
+
+	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
+				 g_hash_table_lookup(chat->components, "channel"),
+				 "+p", NULL);
+}
+
+static void
+silcpurple_chat_resetsecret(PurpleBlistNode *node, gpointer data)
+{
+	PurpleChat *chat;
+	PurpleConnection *gc;
+	SilcPurple sg;
+
+	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
+
+	chat = (PurpleChat *) node;
+	gc = purple_account_get_connection(chat->account);
+	sg = gc->proto_data;
+
+	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
+				 g_hash_table_lookup(chat->components, "channel"),
+				 "-s", NULL);
+}
+
+static void
+silcpurple_chat_setsecret(PurpleBlistNode *node, gpointer data)
+{
+	PurpleChat *chat;
+	PurpleConnection *gc;
+	SilcPurple sg;
+
+	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
+
+	chat = (PurpleChat *) node;
+	gc = purple_account_get_connection(chat->account);
+	sg = gc->proto_data;
+
+	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
+				 g_hash_table_lookup(chat->components, "channel"),
+				 "+s", NULL);
+}
+
+typedef struct {
+	SilcPurple sg;
+	SilcChannelEntry channel;
+} *SilcPurpleChatWb;
+
+static void
+silcpurple_chat_wb(PurpleBlistNode *node, gpointer data)
+{
+	SilcPurpleChatWb wb = data;
+	silcpurple_wb_init_ch(wb->sg, wb->channel);
+	silc_free(wb);
+}
+
+GList *silcpurple_chat_menu(PurpleChat *chat)
+{
+	GHashTable *components = chat->components;
+	PurpleConnection *gc = purple_account_get_connection(chat->account);
+	SilcPurple sg = gc->proto_data;
+	SilcClientConnection conn = sg->conn;
+	const char *chname = NULL;
+	SilcChannelEntry channel = NULL;
+	SilcChannelUser chu = NULL;
+	SilcUInt32 mode = 0;
+
+	GList *m = NULL;
+	PurpleMenuAction *act;
+
+	if (components)
+		chname = g_hash_table_lookup(components, "channel");
+	if (chname)
+		channel = silc_client_get_channel(sg->client, sg->conn,
+						  (char *)chname);
+	if (channel) {
+		chu = silc_client_on_channel(channel, conn->local_entry);
+		if (chu)
+			mode = chu->mode;
+	}
+
+	if (strstr(chname, "[Private Group]"))
+		return NULL;
+
+	act = purple_menu_action_new(_("Get Info"),
+	                           PURPLE_CALLBACK(silcpurple_chat_getinfo_menu),
+	                           NULL, NULL);
+	m = g_list_append(m, act);
+
+#if 0   /* XXX For now these are not implemented.  We need better
+	   listview dialog from Purple for these. */
+	if (mode & SILC_CHANNEL_UMODE_CHANOP) {
+		act = purple_menu_action_new(_("Invite List"),
+		                           PURPLE_CALLBACK(silcpurple_chat_invitelist),
+		                           NULL, NULL);
+		m = g_list_append(m, act);
+
+		act = purple_menu_action_new(_("Ban List"),
+		                           PURPLE_CALLBACK(silcpurple_chat_banlist),
+		                           NULL, NULL);
+		m = g_list_append(m, act);
+	}
+#endif
+
+	if (chu) {
+		act = purple_menu_action_new(_("Add Private Group"),
+		                           PURPLE_CALLBACK(silcpurple_chat_prv),
+		                           NULL, NULL);
+		m = g_list_append(m, act);
+	}
+
+	if (mode & SILC_CHANNEL_UMODE_CHANFO) {
+		act = purple_menu_action_new(_("Channel Authentication"),
+		                           PURPLE_CALLBACK(silcpurple_chat_chauth),
+		                           NULL, NULL);
+		m = g_list_append(m, act);
+
+		if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
+			act = purple_menu_action_new(_("Reset Permanent"),
+			                           PURPLE_CALLBACK(silcpurple_chat_permanent_reset),
+			                           NULL, NULL);
+			m = g_list_append(m, act);
+		} else {
+			act = purple_menu_action_new(_("Set Permanent"),
+			                           PURPLE_CALLBACK(silcpurple_chat_permanent),
+			                           NULL, NULL);
+			m = g_list_append(m, act);
+		}
+	}
+
+	if (mode & SILC_CHANNEL_UMODE_CHANOP) {
+		act = purple_menu_action_new(_("Set User Limit"),
+		                           PURPLE_CALLBACK(silcpurple_chat_ulimit),
+		                           NULL, NULL);
+		m = g_list_append(m, act);
+
+		if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
+			act = purple_menu_action_new(_("Reset Topic Restriction"),
+			                           PURPLE_CALLBACK(silcpurple_chat_resettopic),
+			                           NULL, NULL);
+			m = g_list_append(m, act);
+		} else {
+			act = purple_menu_action_new(_("Set Topic Restriction"),
+			                           PURPLE_CALLBACK(silcpurple_chat_settopic),
+			                           NULL, NULL);
+			m = g_list_append(m, act);
+		}
+
+		if (channel->mode & SILC_CHANNEL_MODE_PRIVATE) {
+			act = purple_menu_action_new(_("Reset Private Channel"),
+			                           PURPLE_CALLBACK(silcpurple_chat_resetprivate),
+			                           NULL, NULL);
+			m = g_list_append(m, act);
+		} else {
+			act = purple_menu_action_new(_("Set Private Channel"),
+			                           PURPLE_CALLBACK(silcpurple_chat_setprivate),
+			                           NULL, NULL);
+			m = g_list_append(m, act);
+		}
+
+		if (channel->mode & SILC_CHANNEL_MODE_SECRET) {
+			act = purple_menu_action_new(_("Reset Secret Channel"),
+			                           PURPLE_CALLBACK(silcpurple_chat_resetsecret),
+			                           NULL, NULL);
+			m = g_list_append(m, act);
+		} else {
+			act = purple_menu_action_new(_("Set Secret Channel"),
+			                           PURPLE_CALLBACK(silcpurple_chat_setsecret),
+			                           NULL, NULL);
+			m = g_list_append(m, act);
+		}
+	}
+
+	if (channel) {
+		SilcPurpleChatWb wb;
+		wb = silc_calloc(1, sizeof(*wb));
+		wb->sg = sg;
+		wb->channel = channel;
+		act = purple_menu_action_new(_("Draw On Whiteboard"),
+		                           PURPLE_CALLBACK(silcpurple_chat_wb),
+		                           (void *)wb, NULL);
+		m = g_list_append(m, act);
+	}
+
+	return m;
+}
+
+
+/******************************* Joining Etc. ********************************/
+
+void silcpurple_chat_join_done(SilcClient client,
+			     SilcClientConnection conn,
+			     SilcClientEntry *clients,
+			     SilcUInt32 clients_count,
+			     void *context)
+{
+	PurpleConnection *gc = client->application;
+	SilcPurple sg = gc->proto_data;
+	SilcChannelEntry channel = context;
+	PurpleConversation *convo;
+	SilcUInt32 retry = SILC_PTR_TO_32(channel->context);
+	SilcHashTableList htl;
+	SilcChannelUser chu;
+	GList *users = NULL, *flags = NULL;
+	char tmp[256];
+
+	if (!clients && retry < 1) {
+		/* Resolving users failed, try again. */
+		channel->context = SILC_32_TO_PTR(retry + 1);
+		silc_client_get_clients_by_channel(client, conn, channel,
+						   silcpurple_chat_join_done, channel);
+		return;
+	}
+
+	/* Add channel to Purple */
+	channel->context = SILC_32_TO_PTR(++sg->channel_ids);
+	serv_got_joined_chat(gc, sg->channel_ids, channel->channel_name);
+	convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
+							channel->channel_name, sg->account);
+	if (!convo)
+		return;
+
+	/* Add all users to channel */
+	silc_hash_table_list(channel->user_list, &htl);
+	while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
+		PurpleConvChatBuddyFlags f = PURPLE_CBFLAGS_NONE;
+		if (!chu->client->nickname)
+			continue;
+		chu->context = SILC_32_TO_PTR(sg->channel_ids);
+
+		if (chu->mode & SILC_CHANNEL_UMODE_CHANFO)
+			f |= PURPLE_CBFLAGS_FOUNDER;
+		if (chu->mode & SILC_CHANNEL_UMODE_CHANOP)
+			f |= PURPLE_CBFLAGS_OP;
+		users = g_list_append(users, g_strdup(chu->client->nickname));
+		flags = g_list_append(flags, GINT_TO_POINTER(f));
+
+		if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) {
+			if (chu->client == conn->local_entry)
+				g_snprintf(tmp, sizeof(tmp),
+					   _("You are channel founder on <I>%s</I>"),
+					   channel->channel_name);
+			else
+				g_snprintf(tmp, sizeof(tmp),
+					   _("Channel founder on <I>%s</I> is <I>%s</I>"),
+					   channel->channel_name, chu->client->nickname);
+
+			purple_conversation_write(convo, NULL, tmp,
+						PURPLE_MESSAGE_SYSTEM, time(NULL));
+
+		}
+	}
+	silc_hash_table_list_reset(&htl);
+
+	purple_conv_chat_add_users(PURPLE_CONV_CHAT(convo), users, NULL, flags, FALSE);
+	g_list_free(users);
+	g_list_free(flags);
+
+	/* Set topic */
+	if (channel->topic)
+		purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, channel->topic);
+
+	/* Set nick */
+	purple_conv_chat_set_nick(PURPLE_CONV_CHAT(convo), conn->local_entry->nickname);
+}
+
+char *silcpurple_get_chat_name(GHashTable *data)
+{
+	return g_strdup(g_hash_table_lookup(data, "channel"));
+}	
+
+void silcpurple_chat_join(PurpleConnection *gc, GHashTable *data)
+{
+	SilcPurple sg = gc->proto_data;
+	SilcClient client = sg->client;
+	SilcClientConnection conn = sg->conn;
+	const char *channel, *passphrase, *parentch;
+
+	if (!conn)
+		return;
+
+	channel = g_hash_table_lookup(data, "channel");
+	passphrase = g_hash_table_lookup(data, "passphrase");
+
+	/* Check if we are joining a private group.  Handle it
+	   purely locally as it's not a real channel */
+	if (strstr(channel, "[Private Group]")) {
+		SilcChannelEntry channel_entry;
+		SilcChannelPrivateKey key;
+		PurpleChat *c;
+		SilcPurplePrvgrp grp;
+
+		c = purple_blist_find_chat(sg->account, channel);
+		parentch = purple_blist_node_get_string((PurpleBlistNode *)c, "parentch");
+		if (!parentch)
+			return;
+
+		channel_entry = silc_client_get_channel(sg->client, sg->conn,
+							(char *)parentch);
+		if (!channel_entry ||
+		    !silc_client_on_channel(channel_entry, sg->conn->local_entry)) {
+			char tmp[512];
+			g_snprintf(tmp, sizeof(tmp),
+				   _("You have to join the %s channel before you are "
+				     "able to join the private group"), parentch);
+			purple_notify_error(gc, _("Join Private Group"),
+					  _("Cannot join private group"), tmp);
+			return;
+		}
+
+		/* Add channel private key */
+		if (!silc_client_add_channel_private_key(client, conn,
+							 channel_entry, channel,
+							 NULL, NULL,
+							 (unsigned char *)passphrase,
+							 strlen(passphrase), &key))
+			return;
+
+		/* Join the group */
+		grp = silc_calloc(1, sizeof(*grp));
+		if (!grp)
+			return;
+		grp->id = ++sg->channel_ids + SILCPURPLE_PRVGRP;
+		grp->chid = SILC_PTR_TO_32(channel_entry->context);
+		grp->parentch = parentch;
+		grp->channel = channel;
+		grp->key = key;
+		sg->grps = g_list_append(sg->grps, grp);
+		serv_got_joined_chat(gc, grp->id, channel);
+		return;
+	}
+
+	/* XXX We should have other properties here as well:
+	   1. whether to try to authenticate to the channel
+	     1a. with default key,
+	     1b. with specific key.
+	   2. whether to try to authenticate to become founder.
+	     2a. with default key,
+	     2b. with specific key.
+
+	   Since now such variety is not possible in the join dialog
+	   we always use -founder and -auth options, which try to
+	   do both 1 and 2 with default keys. */
+
+	/* Call JOIN */
+	if ((passphrase != NULL) && (*passphrase != '\0'))
+		silc_client_command_call(client, conn, NULL, "JOIN",
+					 channel, passphrase, "-auth", "-founder", NULL);
+	else
+		silc_client_command_call(client, conn, NULL, "JOIN",
+					 channel, "-auth", "-founder", NULL);
+}
+
+void silcpurple_chat_invite(PurpleConnection *gc, int id, const char *msg,
+			  const char *name)
+{
+	SilcPurple sg = gc->proto_data;
+	SilcClient client = sg->client;
+	SilcClientConnection conn = sg->conn;
+	SilcHashTableList htl;
+	SilcChannelUser chu;
+	gboolean found = FALSE;
+
+	if (!conn)
+		return;
+
+	/* See if we are inviting on a private group.  Invite
+	   to the actual channel */
+	if (id > SILCPURPLE_PRVGRP) {
+		GList *l;
+		SilcPurplePrvgrp prv;
+
+		for (l = sg->grps; l; l = l->next)
+			if (((SilcPurplePrvgrp)l->data)->id == id)
+				break;
+		if (!l)
+			return;
+		prv = l->data;
+		id = prv->chid;
+	}
+
+	/* Find channel by id */
+	silc_hash_table_list(conn->local_entry->channels, &htl);
+	while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
+		if (SILC_PTR_TO_32(chu->channel->context) == id ) {
+			found = TRUE;
+			break;
+		}
+	}
+	silc_hash_table_list_reset(&htl);
+	if (!found)
+		return;
+
+	/* Call INVITE */
+	silc_client_command_call(client, conn, NULL, "INVITE",
+				 chu->channel->channel_name,
+				 name, NULL);
+}
+
+void silcpurple_chat_leave(PurpleConnection *gc, int id)
+{
+	SilcPurple sg = gc->proto_data;
+	SilcClient client = sg->client;
+	SilcClientConnection conn = sg->conn;
+	SilcHashTableList htl;
+	SilcChannelUser chu;
+	gboolean found = FALSE;
+	GList *l;
+	SilcPurplePrvgrp prv;
+
+	if (!conn)
+		return;
+
+	/* See if we are leaving a private group */
+	if (id > SILCPURPLE_PRVGRP) {
+		SilcChannelEntry channel;
+
+		for (l = sg->grps; l; l = l->next)
+			if (((SilcPurplePrvgrp)l->data)->id == id)
+				break;
+		if (!l)
+			return;
+		prv = l->data;
+		channel = silc_client_get_channel(sg->client, sg->conn,
+						  (char *)prv->parentch);
+		if (!channel)
+			return;
+		silc_client_del_channel_private_key(client, conn,
+						    channel, prv->key);
+		silc_free(prv);
+		sg->grps = g_list_remove(sg->grps, prv);
+		serv_got_chat_left(gc, id);
+		return;
+	}
+
+	/* Find channel by id */
+	silc_hash_table_list(conn->local_entry->channels, &htl);
+	while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
+		if (SILC_PTR_TO_32(chu->channel->context) == id ) {
+			found = TRUE;
+			break;
+		}
+	}
+	silc_hash_table_list_reset(&htl);
+	if (!found)
+		return;
+
+	/* Call LEAVE */
+	silc_client_command_call(client, conn, NULL, "LEAVE",
+				 chu->channel->channel_name, NULL);
+
+	serv_got_chat_left(gc, id);
+
+	/* Leave from private groups on this channel as well */
+	for (l = sg->grps; l; l = l->next)
+		if (((SilcPurplePrvgrp)l->data)->chid == id) {
+			prv = l->data;
+			silc_client_del_channel_private_key(client, conn,
+							    chu->channel,
+							    prv->key);
+			serv_got_chat_left(gc, prv->id);
+			silc_free(prv);
+			sg->grps = g_list_remove(sg->grps, prv);
+			if (!sg->grps)
+				break;
+		}
+}
+
+int silcpurple_chat_send(PurpleConnection *gc, int id, const char *msg, PurpleMessageFlags msgflags)
+{
+	SilcPurple sg = gc->proto_data;
+	SilcClient client = sg->client;
+	SilcClientConnection conn = sg->conn;
+	SilcHashTableList htl;
+	SilcChannelUser chu;
+	SilcChannelEntry channel = NULL;
+	SilcChannelPrivateKey key = NULL;
+	SilcUInt32 flags;
+	int ret;
+	char *msg2, *tmp;
+	gboolean found = FALSE;
+	gboolean sign = purple_account_get_bool(sg->account, "sign-verify", FALSE);
+
+	if (!msg || !conn)
+		return 0;
+
+	flags = SILC_MESSAGE_FLAG_UTF8;
+
+	tmp = msg2 = purple_unescape_html(msg);
+
+	if (!g_ascii_strncasecmp(msg2, "/me ", 4))
+	{
+		msg2 += 4;
+		if (!*msg2) {
+			g_free(tmp);
+			return 0;
+		}
+		flags |= SILC_MESSAGE_FLAG_ACTION;
+	} else if (strlen(msg) > 1 && msg[0] == '/') {
+		if (!silc_client_command_call(client, conn, msg + 1))
+			purple_notify_error(gc, _("Call Command"), _("Cannot call command"),
+							  _("Unknown command"));
+		g_free(tmp);
+		return 0;
+	}
+
+
+	if (sign)
+		flags |= SILC_MESSAGE_FLAG_SIGNED;
+
+	/* Get the channel private key if we are sending on
+	   private group */
+	if (id > SILCPURPLE_PRVGRP) {
+		GList *l;
+		SilcPurplePrvgrp prv;
+
+		for (l = sg->grps; l; l = l->next)
+			if (((SilcPurplePrvgrp)l->data)->id == id)
+				break;
+		if (!l) {
+			g_free(tmp);
+			return 0;
+		}
+		prv = l->data;
+		channel = silc_client_get_channel(sg->client, sg->conn,
+						  (char *)prv->parentch);
+		if (!channel) {
+			g_free(tmp);
+			return 0;
+		}
+		key = prv->key;
+	}
+
+	if (!channel) {
+		/* Find channel by id */
+		silc_hash_table_list(conn->local_entry->channels, &htl);
+		while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
+			if (SILC_PTR_TO_32(chu->channel->context) == id ) {
+				found = TRUE;
+				break;
+			}
+		}
+		silc_hash_table_list_reset(&htl);
+		if (!found) {
+			g_free(tmp);
+			return 0;
+		}
+		channel = chu->channel;
+	}
+
+	/* Send channel message */
+	ret = silc_client_send_channel_message(client, conn, channel, key,
+					       flags, (unsigned char *)msg2,
+					       strlen(msg2), TRUE);
+	if (ret) {
+		serv_got_chat_in(gc, id, purple_connection_get_display_name(gc), 0, msg,
+				 time(NULL));
+	}
+	g_free(tmp);
+
+	return ret;
+}
+
+void silcpurple_chat_set_topic(PurpleConnection *gc, int id, const char *topic)
+{
+	SilcPurple sg = gc->proto_data;
+	SilcClient client = sg->client;
+	SilcClientConnection conn = sg->conn;
+	SilcHashTableList htl;
+	SilcChannelUser chu;
+	gboolean found = FALSE;
+
+	if (!conn)
+		return;
+
+	/* See if setting topic on private group.  Set it
+	   on the actual channel */
+	if (id > SILCPURPLE_PRVGRP) {
+		GList *l;
+		SilcPurplePrvgrp prv;
+
+		for (l = sg->grps; l; l = l->next)
+			if (((SilcPurplePrvgrp)l->data)->id == id)
+				break;
+		if (!l)
+			return;
+		prv = l->data;
+		id = prv->chid;
+	}
+
+	/* Find channel by id */
+	silc_hash_table_list(conn->local_entry->channels, &htl);
+	while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
+		if (SILC_PTR_TO_32(chu->channel->context) == id ) {
+			found = TRUE;
+			break;
+		}
+	}
+	silc_hash_table_list_reset(&htl);
+	if (!found)
+		return;
+
+	/* Call TOPIC */
+	silc_client_command_call(client, conn, NULL, "TOPIC",
+				 chu->channel->channel_name, topic, NULL);
+}
+
+PurpleRoomlist *silcpurple_roomlist_get_list(PurpleConnection *gc)
+{
+	SilcPurple sg = gc->proto_data;
+	SilcClient client = sg->client;
+	SilcClientConnection conn = sg->conn;
+	GList *fields = NULL;
+	PurpleRoomlistField *f;
+
+	if (!conn)
+		return NULL;
+
+	if (sg->roomlist)
+		purple_roomlist_unref(sg->roomlist);
+
+	sg->roomlist_canceled = FALSE;
+
+	sg->roomlist = purple_roomlist_new(purple_connection_get_account(gc));
+	f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", "channel", TRUE);
+	fields = g_list_append(fields, f);
+	f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_INT,
+				    _("Users"), "users", FALSE);
+	fields = g_list_append(fields, f);
+	f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING,
+				    _("Topic"), "topic", FALSE);
+	fields = g_list_append(fields, f);
+	purple_roomlist_set_fields(sg->roomlist, fields);
+
+	/* Call LIST */
+	silc_client_command_call(client, conn, "LIST");
+
+	purple_roomlist_set_in_progress(sg->roomlist, TRUE);
+
+	return sg->roomlist;
+}
+
+void silcpurple_roomlist_cancel(PurpleRoomlist *list)
+{
+	PurpleConnection *gc = purple_account_get_connection(list->account);
+	SilcPurple sg;
+
+	if (!gc)
+		return;
+	sg = gc->proto_data;
+
+	purple_roomlist_set_in_progress(list, FALSE);
+	if (sg->roomlist == list) {
+		purple_roomlist_unref(sg->roomlist);
+		sg->roomlist = NULL;
+		sg->roomlist_canceled = TRUE;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/silc10/ft.c	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,412 @@
+/*
+
+  silcpurple_ft.c
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2004 Pekka Riikonen
+
+  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; version 2 of the License.
+
+  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.
+
+*/
+
+#include "silcincludes.h"
+#include "silcclient.h"
+#include "silcpurple.h"
+
+/****************************** File Transfer ********************************/
+
+/* This implements the secure file transfer protocol (SFTP) using the SILC
+   SFTP library implementation.  The API we use from the SILC Toolkit is the
+   SILC Client file transfer API, as it provides a simple file transfer we
+   need in this case.  We could use the SILC SFTP API directly, but it would
+   be an overkill since we'd effectively re-implement the file transfer what
+   the SILC Client's file transfer API already provides.
+
+   From Purple we do NOT use the FT API to do the transfer as it is very limiting.
+   In fact it does not suite to file transfers like SFTP at all.  For example,
+   it assumes that read operations are synchronous what they are not in SFTP.
+   It also assumes that the file transfer socket is to be handled by the Purple
+   eventloop, and this naturally is something we don't want to do in case of
+   SILC Toolkit.  The FT API suites well to purely stream based file transfers
+   like HTTP GET and similar.
+
+   For this reason, we directly access the Purple GKT FT API and hack the FT
+   API to merely provide the user interface experience and all the magic
+   is done in the SILC Toolkit.  Ie. we update the statistics information in
+   the FT API for user interface, and that's it.  A bit dirty but until the
+   FT API gets better this is the way to go.  Good thing that FT API allowed
+   us to do this. */
+
+typedef struct {
+	SilcPurple sg;
+	SilcClientEntry client_entry;
+	SilcUInt32 session_id;
+	char *hostname;
+	SilcUInt16 port;
+	PurpleXfer *xfer;
+
+	SilcClientFileName completion;
+	void *completion_context;
+} *SilcPurpleXfer;
+
+static void
+silcpurple_ftp_monitor(SilcClient client,
+		     SilcClientConnection conn,
+		     SilcClientMonitorStatus status,
+		     SilcClientFileError error,
+		     SilcUInt64 offset,
+		     SilcUInt64 filesize,
+		     SilcClientEntry client_entry,
+		     SilcUInt32 session_id,
+		     const char *filepath,
+		     void *context)
+{
+	SilcPurpleXfer xfer = context;
+	PurpleConnection *gc = xfer->sg->gc;
+	char tmp[256];
+
+	if (status == SILC_CLIENT_FILE_MONITOR_CLOSED) {
+		purple_xfer_unref(xfer->xfer);
+		silc_free(xfer);
+		return;
+	}
+
+	if (status == SILC_CLIENT_FILE_MONITOR_KEY_AGREEMENT)
+		return;
+
+	if (status == SILC_CLIENT_FILE_MONITOR_ERROR) {
+		if (error == SILC_CLIENT_FILE_NO_SUCH_FILE) {
+			g_snprintf(tmp, sizeof(tmp), "No such file %s",
+				   filepath ? filepath : "[N/A]");
+			purple_notify_error(gc, _("Secure File Transfer"),
+					  _("Error during file transfer"), tmp);
+		} else if (error == SILC_CLIENT_FILE_PERMISSION_DENIED) {
+			purple_notify_error(gc, _("Secure File Transfer"),
+					  _("Error during file transfer"),
+					  _("Permission denied"));
+		} else if (error == SILC_CLIENT_FILE_KEY_AGREEMENT_FAILED) {
+			purple_notify_error(gc, _("Secure File Transfer"),
+					  _("Error during file transfer"),
+					  _("Key agreement failed"));
+		} else if (error == SILC_CLIENT_FILE_UNKNOWN_SESSION) {
+			purple_notify_error(gc, _("Secure File Transfer"),
+					  _("Error during file transfer"),
+					  _("File transfer session does not exist"));
+		} else {
+			purple_notify_error(gc, _("Secure File Transfer"),
+					  _("Error during file transfer"), NULL);
+		}
+		silc_client_file_close(client, conn, session_id);
+		purple_xfer_unref(xfer->xfer);
+		silc_free(xfer);
+		return;
+	}
+
+	/* Update file transfer UI */
+	if (!offset && filesize)
+		purple_xfer_set_size(xfer->xfer, filesize);
+	if (offset && filesize) {
+		xfer->xfer->bytes_sent = offset;
+		xfer->xfer->bytes_remaining = filesize - offset;
+	}
+	purple_xfer_update_progress(xfer->xfer);
+
+	if (status == SILC_CLIENT_FILE_MONITOR_SEND ||
+	    status == SILC_CLIENT_FILE_MONITOR_RECEIVE) {
+		if (offset == filesize) {
+			/* Download finished */
+			purple_xfer_set_completed(xfer->xfer, TRUE);
+			silc_client_file_close(client, conn, session_id);
+		}
+	}
+}
+
+static void
+silcpurple_ftp_cancel(PurpleXfer *x)
+{
+	SilcPurpleXfer xfer = x->data;
+	xfer->xfer->status = PURPLE_XFER_STATUS_CANCEL_LOCAL;
+	purple_xfer_update_progress(xfer->xfer);
+	silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id);
+}
+
+static void
+silcpurple_ftp_ask_name_cancel(PurpleXfer *x)
+{
+	SilcPurpleXfer xfer = x->data;
+
+	/* Cancel the transmission */
+	xfer->completion(NULL, xfer->completion_context);
+	silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id);
+}
+
+static void
+silcpurple_ftp_ask_name_ok(PurpleXfer *x)
+{
+	SilcPurpleXfer xfer = x->data;
+	const char *name;
+
+	name = purple_xfer_get_local_filename(x);
+	g_unlink(name);
+	xfer->completion(name, xfer->completion_context);
+}
+
+static void
+silcpurple_ftp_ask_name(SilcClient client,
+		      SilcClientConnection conn,
+		      SilcUInt32 session_id,
+		      const char *remote_filename,
+		      SilcClientFileName completion,
+		      void *completion_context,
+		      void *context)
+{
+	SilcPurpleXfer xfer = context;
+
+	xfer->completion = completion;
+	xfer->completion_context = completion_context;
+
+	purple_xfer_set_init_fnc(xfer->xfer, silcpurple_ftp_ask_name_ok);
+	purple_xfer_set_request_denied_fnc(xfer->xfer, silcpurple_ftp_ask_name_cancel);
+
+	/* Request to save the file */
+	purple_xfer_set_filename(xfer->xfer, remote_filename);
+	purple_xfer_request(xfer->xfer);
+}
+
+static void
+silcpurple_ftp_request_result(PurpleXfer *x)
+{
+	SilcPurpleXfer xfer = x->data;
+	SilcClientFileError status;
+	PurpleConnection *gc = xfer->sg->gc;
+
+	if (purple_xfer_get_status(x) != PURPLE_XFER_STATUS_ACCEPTED)
+		return;
+
+	/* Start the file transfer */
+	status = silc_client_file_receive(xfer->sg->client, xfer->sg->conn,
+					  silcpurple_ftp_monitor, xfer,
+					  NULL, xfer->session_id,
+					  silcpurple_ftp_ask_name, xfer);
+	switch (status) {
+	case SILC_CLIENT_FILE_OK:
+		return;
+		break;
+
+	case SILC_CLIENT_FILE_UNKNOWN_SESSION:
+		purple_notify_error(gc, _("Secure File Transfer"),
+				  _("No file transfer session active"), NULL);
+		break;
+
+	case SILC_CLIENT_FILE_ALREADY_STARTED:
+		purple_notify_error(gc, _("Secure File Transfer"),
+				  _("File transfer already started"), NULL);
+		break;
+
+	case SILC_CLIENT_FILE_KEY_AGREEMENT_FAILED:
+		purple_notify_error(gc, _("Secure File Transfer"),
+				  _("Could not perform key agreement for file transfer"),
+				  NULL);
+		break;
+
+	default:
+		purple_notify_error(gc, _("Secure File Transfer"),
+				  _("Could not start the file transfer"), NULL);
+		break;
+	}
+
+	/* Error */
+	purple_xfer_unref(xfer->xfer);
+	g_free(xfer->hostname);
+	silc_free(xfer);
+}
+
+static void
+silcpurple_ftp_request_denied(PurpleXfer *x)
+{
+
+}
+
+void silcpurple_ftp_request(SilcClient client, SilcClientConnection conn,
+			  SilcClientEntry client_entry, SilcUInt32 session_id,
+			  const char *hostname, SilcUInt16 port)
+{
+	PurpleConnection *gc = client->application;
+	SilcPurple sg = gc->proto_data;
+	SilcPurpleXfer xfer;
+
+	xfer = silc_calloc(1, sizeof(*xfer));
+	if (!xfer) {
+		silc_client_file_close(sg->client, sg->conn, session_id);
+		return;
+	}
+
+	xfer->sg = sg;
+	xfer->client_entry = client_entry;
+	xfer->session_id = session_id;
+	xfer->hostname = g_strdup(hostname);
+	xfer->port = port;
+	xfer->xfer = purple_xfer_new(xfer->sg->account, PURPLE_XFER_RECEIVE,
+				   xfer->client_entry->nickname);
+	if (!xfer->xfer) {
+		silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id);
+		g_free(xfer->hostname);
+		silc_free(xfer);
+		return;
+	}
+	purple_xfer_set_init_fnc(xfer->xfer, silcpurple_ftp_request_result);
+	purple_xfer_set_request_denied_fnc(xfer->xfer, silcpurple_ftp_request_denied);
+	purple_xfer_set_cancel_recv_fnc(xfer->xfer, silcpurple_ftp_cancel);
+	xfer->xfer->remote_ip = g_strdup(hostname);
+	xfer->xfer->remote_port = port;
+	xfer->xfer->data = xfer;
+
+	/* File transfer request */
+	purple_xfer_request(xfer->xfer);
+}
+
+static void
+silcpurple_ftp_send_cancel(PurpleXfer *x)
+{
+	SilcPurpleXfer xfer = x->data;
+	silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id);
+	purple_xfer_unref(xfer->xfer);
+	g_free(xfer->hostname);
+	silc_free(xfer);
+}
+
+static void
+silcpurple_ftp_send(PurpleXfer *x)
+{
+	SilcPurpleXfer xfer = x->data;
+	const char *name;
+	char *local_ip = NULL, *remote_ip = NULL;
+	gboolean local = TRUE;
+
+	name = purple_xfer_get_local_filename(x);
+
+	/* Do the same magic what we do with key agreement (see silcpurple_buddy.c)
+	   to see if we are behind NAT. */
+	if (silc_net_check_local_by_sock(xfer->sg->conn->sock->sock,
+					 NULL, &local_ip)) {
+		/* Check if the IP is private */
+		if (silcpurple_ip_is_private(local_ip)) {
+			local = FALSE;
+			/* Local IP is private, resolve the remote server IP to see whether
+			   we are talking to Internet or just on LAN. */
+			if (silc_net_check_host_by_sock(xfer->sg->conn->sock->sock, NULL,
+							&remote_ip))
+				if (silcpurple_ip_is_private(remote_ip))
+					/* We assume we are in LAN.  Let's provide the connection point. */
+					local = TRUE;
+		}
+	}
+
+	if (local && !local_ip)
+		local_ip = silc_net_localip();
+
+	/* Send the file */
+	silc_client_file_send(xfer->sg->client, xfer->sg->conn,
+			      silcpurple_ftp_monitor, xfer,
+			      local_ip, 0, !local, xfer->client_entry,
+			      name, &xfer->session_id);
+
+	silc_free(local_ip);
+	silc_free(remote_ip);
+}
+
+static void
+silcpurple_ftp_send_file_resolved(SilcClient client,
+				SilcClientConnection conn,
+				SilcClientEntry *clients,
+				SilcUInt32 clients_count,
+				void *context)
+{
+	PurpleConnection *gc = client->application;
+	char tmp[256];
+
+	if (!clients) {
+		g_snprintf(tmp, sizeof(tmp),
+			   _("User %s is not present in the network"),
+			   (const char *)context);
+		purple_notify_error(gc, _("Secure File Transfer"),
+				  _("Cannot send file"), tmp);
+		silc_free(context);
+		return;
+	}
+
+	silcpurple_ftp_send_file(client->application, (const char *)context, NULL);
+	silc_free(context);
+}
+
+PurpleXfer *silcpurple_ftp_new_xfer(PurpleConnection *gc, const char *name)
+{
+	SilcPurple sg = gc->proto_data;
+	SilcClient client = sg->client;
+	SilcClientConnection conn = sg->conn;
+	SilcClientEntry *clients;
+	SilcUInt32 clients_count;
+	SilcPurpleXfer xfer;
+	char *nickname;
+
+	g_return_val_if_fail(name != NULL, NULL);
+
+	if (!silc_parse_userfqdn(name, &nickname, NULL))
+		return NULL;
+
+	/* Find client entry */
+	clients = silc_client_get_clients_local(client, conn, nickname, name,
+											&clients_count);
+	if (!clients) {
+		silc_client_get_clients(client, conn, nickname, NULL,
+								silcpurple_ftp_send_file_resolved,
+								strdup(name));
+		silc_free(nickname);
+		return NULL;
+	}
+
+	xfer = silc_calloc(1, sizeof(*xfer));
+
+	g_return_val_if_fail(xfer != NULL, NULL);
+
+	xfer->sg = sg;
+	xfer->client_entry = clients[0];
+	xfer->xfer = purple_xfer_new(xfer->sg->account, PURPLE_XFER_SEND,
+							   xfer->client_entry->nickname);
+	if (!xfer->xfer) {
+		silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id);
+		g_free(xfer->hostname);
+		silc_free(xfer);
+		return NULL;
+	}
+	purple_xfer_set_init_fnc(xfer->xfer, silcpurple_ftp_send);
+	purple_xfer_set_request_denied_fnc(xfer->xfer, silcpurple_ftp_request_denied);
+	purple_xfer_set_cancel_send_fnc(xfer->xfer, silcpurple_ftp_send_cancel);
+	xfer->xfer->data = xfer;
+
+	silc_free(clients);
+	silc_free(nickname);
+
+	return xfer->xfer;
+}
+
+void silcpurple_ftp_send_file(PurpleConnection *gc, const char *name, const char *file)
+{
+	PurpleXfer *xfer = silcpurple_ftp_new_xfer(gc, name);
+
+	g_return_if_fail(xfer != NULL);
+
+	/* Choose file to send */
+	if (file)
+		purple_xfer_request_accepted(xfer, file);
+	else
+		purple_xfer_request(xfer);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/silc10/ops.c	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,2057 @@
+/*
+
+  silcpurple_ops.c
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2004 Pekka Riikonen
+
+  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; version 2 of the License.
+
+  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.
+
+*/
+
+#include "silcincludes.h"
+#include "silcclient.h"
+#include "silcpurple.h"
+#include "imgstore.h"
+#include "wb.h"
+
+static void
+silc_channel_message(SilcClient client, SilcClientConnection conn,
+		     SilcClientEntry sender, SilcChannelEntry channel,
+		     SilcMessagePayload payload, SilcChannelPrivateKey key,
+		     SilcMessageFlags flags, const unsigned char *message,
+		     SilcUInt32 message_len);
+static void
+silc_private_message(SilcClient client, SilcClientConnection conn,
+		     SilcClientEntry sender, SilcMessagePayload payload,
+		     SilcMessageFlags flags, const unsigned char *message,
+		     SilcUInt32 message_len);
+
+/* Message sent to the application by library. `conn' associates the
+   message to a specific connection.  `conn', however, may be NULL.
+   The `type' indicates the type of the message sent by the library.
+   The application can for example filter the message according the
+   type. */
+
+static void
+silc_say(SilcClient client, SilcClientConnection conn,
+	 SilcClientMessageType type, char *msg, ...)
+{
+	/* Nothing */
+}
+
+#ifdef HAVE_SILCMIME_H
+/* Processes incoming MIME message.  Can be private message or channel
+   message. */
+
+static void
+silcpurple_mime_message(SilcClient client, SilcClientConnection conn,
+		      SilcClientEntry sender, SilcChannelEntry channel,
+		      SilcMessagePayload payload, SilcChannelPrivateKey key,
+		      SilcMessageFlags flags, SilcMime mime,
+		      gboolean recursive)
+{
+	PurpleConnection *gc = client->application;
+	SilcPurple sg = gc->proto_data;
+	const char *type;
+	const unsigned char *data;
+	SilcUInt32 data_len;
+	PurpleMessageFlags cflags = 0;
+	PurpleConversation *convo = NULL;
+
+	if (!mime)
+		return;
+
+	/* Check for fragmented MIME message */
+	if (silc_mime_is_partial(mime)) {
+		if (!sg->mimeass)
+			sg->mimeass = silc_mime_assembler_alloc();
+
+		/* Defragment */
+		mime = silc_mime_assemble(sg->mimeass, mime);
+		if (!mime)
+			/* More fragments to come */
+			return;
+
+		/* Process the complete message */
+		silcpurple_mime_message(client, conn, sender, channel,
+				      payload, key, flags, mime, FALSE);
+		return;
+	}
+
+	/* Check for multipart message */
+	if (silc_mime_is_multipart(mime)) {
+		SilcMime p;
+		const char *mtype;
+		SilcDList parts = silc_mime_get_multiparts(mime, &mtype);
+
+		/* Only "mixed" type supported */
+		if (strcmp(mtype, "mixed"))
+			goto out;
+
+		silc_dlist_start(parts);
+		while ((p = silc_dlist_get(parts)) != SILC_LIST_END) {
+			/* Recursively process parts */
+			silcpurple_mime_message(client, conn, sender, channel,
+					      payload, key, flags, p, TRUE);
+		}
+		goto out;
+	}
+
+	/* Get content type and MIME data */
+	type = silc_mime_get_field(mime, "Content-Type");
+	if (!type)
+		goto out;
+	data = silc_mime_get_data(mime, &data_len);
+	if (!data)
+		goto out;
+
+	/* Process according to content type */
+
+	/* Plain text */
+	if (strstr(type, "text/plain")) {
+		/* Default is UTF-8, don't check for other charsets */
+		if (!strstr(type, "utf-8"))
+			goto out;
+
+		if (channel)
+			silc_channel_message(client, conn, sender, channel,
+					     payload, key, 
+					     SILC_MESSAGE_FLAG_UTF8, data,
+					     data_len);
+		else
+			silc_private_message(client, conn, sender, payload,
+					     SILC_MESSAGE_FLAG_UTF8, data,
+					     data_len);
+		goto out;
+	}
+
+	/* Image */
+	if (strstr(type, "image/png") ||
+	    strstr(type, "image/jpeg") ||
+	    strstr(type, "image/gif") ||
+	    strstr(type, "image/tiff")) {
+		char tmp[32];
+		int imgid;
+
+		/* Get channel convo (if message is for channel) */
+		if (key && channel) {
+			GList *l;
+			SilcPurplePrvgrp prv;
+
+			for (l = sg->grps; l; l = l->next)
+				if (((SilcPurplePrvgrp)l->data)->key == key) {
+					prv = l->data;
+					convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
+							prv->channel, sg->account);
+					break;
+				}
+		}
+		if (channel && !convo)
+			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
+								    channel->channel_name, sg->account);
+		if (channel && !convo)
+			goto out;
+
+		imgid = purple_imgstore_add_with_id(g_memdup(data, data_len), data_len, "");
+		if (imgid) {
+			cflags |= PURPLE_MESSAGE_IMAGES | PURPLE_MESSAGE_RECV;
+			g_snprintf(tmp, sizeof(tmp), "<IMG ID=\"%d\">", imgid);
+		  
+			if (channel)
+				serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)),
+				 		 sender->nickname ?
+				 		  sender->nickname : 
+						 "<unknown>", cflags,
+						 tmp, time(NULL));
+			else
+				serv_got_im(gc, sender->nickname ?
+					    sender->nickname : "<unknown>",
+					    tmp, cflags, time(NULL));
+
+			purple_imgstore_unref_by_id(imgid);
+			cflags = 0;
+		}
+		goto out;
+	}
+
+	/* Whiteboard message */
+	if (strstr(type, "application/x-wb") &&
+	    !purple_account_get_bool(sg->account, "block-wb", FALSE)) {
+		if (channel)
+			silcpurple_wb_receive_ch(client, conn, sender, channel,
+					       payload, flags, data, data_len);
+		else
+			silcpurple_wb_receive(client, conn, sender, payload,
+					    flags, data, data_len);
+		goto out;
+	}
+
+ out:
+	if (!recursive)
+		silc_mime_free(mime);
+}
+#endif /* HAVE_SILCMIME_H */
+
+/* Message for a channel. The `sender' is the sender of the message
+   The `channel' is the channel. The `message' is the message.  Note
+   that `message' maybe NULL.  The `flags' indicates message flags
+   and it is used to determine how the message can be interpreted
+   (like it may tell the message is multimedia message). */
+
+static void
+silc_channel_message(SilcClient client, SilcClientConnection conn,
+		     SilcClientEntry sender, SilcChannelEntry channel,
+		     SilcMessagePayload payload, SilcChannelPrivateKey key,
+		     SilcMessageFlags flags, const unsigned char *message,
+		     SilcUInt32 message_len)
+{
+	PurpleConnection *gc = client->application;
+	SilcPurple sg = gc->proto_data;
+	PurpleConversation *convo = NULL;
+	char *msg, *tmp;
+
+	if (!message)
+		return;
+
+	if (key) {
+		GList *l;
+		SilcPurplePrvgrp prv;
+
+		for (l = sg->grps; l; l = l->next)
+			if (((SilcPurplePrvgrp)l->data)->key == key) {
+				prv = l->data;
+				convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
+										prv->channel, sg->account);
+				break;
+			}
+	}
+	if (!convo)
+		convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
+								channel->channel_name, sg->account);
+	if (!convo)
+		return;
+
+	if (flags & SILC_MESSAGE_FLAG_SIGNED &&
+	    purple_account_get_bool(sg->account, "sign-verify", FALSE)) {
+		/* XXX */
+	}
+
+	if (flags & SILC_MESSAGE_FLAG_DATA) {
+		/* Process MIME message */
+#ifdef HAVE_SILCMIME_H
+		SilcMime mime;
+		mime = silc_mime_decode(message, message_len);
+		silcpurple_mime_message(client, conn, sender, channel, payload,
+				      key, flags, mime, FALSE);
+#else
+		char type[128], enc[128];
+		unsigned char *data;
+		SilcUInt32 data_len;
+
+		memset(type, 0, sizeof(type));
+		memset(enc, 0, sizeof(enc));
+
+		if (!silc_mime_parse(message, message_len, NULL, 0,
+		    type, sizeof(type) - 1, enc, sizeof(enc) - 1, &data,
+		    &data_len))
+			return;
+
+		if (!strcmp(type, "application/x-wb") &&
+		    !strcmp(enc, "binary") &&
+		    !purple_account_get_bool(sg->account, "block-wb", FALSE))
+			silcpurple_wb_receive_ch(client, conn, sender, channel,
+					       payload, flags, data, data_len);
+#endif
+		return;
+	}
+
+	if (flags & SILC_MESSAGE_FLAG_ACTION) {
+		msg = g_strdup_printf("/me %s",
+				      (const char *)message);
+		if (!msg)
+			return;
+
+		tmp = g_markup_escape_text(msg, -1);
+		/* Send to Purple */
+		serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)),
+				 sender->nickname ?
+				 sender->nickname : "<unknown>", 0,
+				 tmp, time(NULL));
+		g_free(tmp);
+		g_free(msg);
+		return;
+	}
+
+	if (flags & SILC_MESSAGE_FLAG_NOTICE) {
+		msg = g_strdup_printf("(notice) <I>%s</I> %s",
+				      sender->nickname ?
+				      sender->nickname : "<unknown>",
+				      (const char *)message);
+		if (!msg)
+			return;
+
+		/* Send to Purple */
+		purple_conversation_write(convo, NULL, (const char *)msg,
+					PURPLE_MESSAGE_SYSTEM, time(NULL));
+		g_free(msg);
+		return;
+	}
+
+	if (flags & SILC_MESSAGE_FLAG_UTF8) {
+		tmp = g_markup_escape_text((const char *)message, -1);
+		/* Send to Purple */
+		serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)),
+				 sender->nickname ?
+				 sender->nickname : "<unknown>", 0,
+				 tmp, time(NULL));
+		g_free(tmp);
+	}
+}
+
+
+/* Private message to the client. The `sender' is the sender of the
+   message. The message is `message'and maybe NULL.  The `flags'
+   indicates message flags  and it is used to determine how the message
+   can be interpreted (like it may tell the message is multimedia
+   message). */
+
+static void
+silc_private_message(SilcClient client, SilcClientConnection conn,
+		     SilcClientEntry sender, SilcMessagePayload payload,
+		     SilcMessageFlags flags, const unsigned char *message,
+		     SilcUInt32 message_len)
+{
+	PurpleConnection *gc = client->application;
+	SilcPurple sg = gc->proto_data;
+	PurpleConversation *convo = NULL;
+	char *msg, *tmp;
+
+	if (!message)
+		return;
+
+	if (sender->nickname)
+		/* XXX - Should this be PURPLE_CONV_TYPE_IM? */
+		convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY,
+								sender->nickname, sg->account);
+
+	if (flags & SILC_MESSAGE_FLAG_SIGNED &&
+	    purple_account_get_bool(sg->account, "sign-verify", FALSE)) {
+		/* XXX */
+	}
+
+	if (flags & SILC_MESSAGE_FLAG_DATA) {
+#ifdef HAVE_SILCMIME_H
+		/* Process MIME message */
+		SilcMime mime;
+		mime = silc_mime_decode(message, message_len);
+		silcpurple_mime_message(client, conn, sender, NULL, payload,
+				      NULL, flags, mime, FALSE);
+#else
+		char type[128], enc[128];
+		unsigned char *data;
+		SilcUInt32 data_len;
+
+		memset(type, 0, sizeof(type));
+		memset(enc, 0, sizeof(enc));
+
+		if (!silc_mime_parse(message, message_len, NULL, 0,
+		    type, sizeof(type) - 1, enc, sizeof(enc) - 1, &data, 
+		    &data_len))
+			return;
+
+		if (!strcmp(type, "application/x-wb") &&
+		    !strcmp(enc, "binary") &&
+		    !purple_account_get_bool(sg->account, "block-wb", FALSE))
+			silcpurple_wb_receive(client, conn, sender, payload,
+					    flags, data, data_len);
+#endif
+		return;
+	}
+
+	if (flags & SILC_MESSAGE_FLAG_ACTION && convo) {
+		msg = g_strdup_printf("/me %s",
+				      (const char *)message);
+		if (!msg)
+			return;
+
+		tmp = g_markup_escape_text(msg, -1);
+		/* Send to Purple */
+		serv_got_im(gc, sender->nickname ?
+			    sender->nickname : "<unknown>",
+			    tmp, 0, time(NULL));
+		g_free(msg);
+		g_free(tmp);
+		return;
+	}
+
+	if (flags & SILC_MESSAGE_FLAG_NOTICE && convo) {
+		msg = g_strdup_printf("(notice) <I>%s</I> %s",
+				      sender->nickname ?
+				      sender->nickname : "<unknown>",
+				      (const char *)message);
+		if (!msg)
+			return;
+
+		/* Send to Purple */
+		purple_conversation_write(convo, NULL, (const char *)msg,
+					PURPLE_MESSAGE_SYSTEM, time(NULL));
+		g_free(msg);
+		return;
+	}
+
+	if (flags & SILC_MESSAGE_FLAG_UTF8) {
+		tmp = g_markup_escape_text((const char *)message, -1);
+		/* Send to Purple */
+		serv_got_im(gc, sender->nickname ?
+			    sender->nickname : "<unknown>",
+			    tmp, 0, time(NULL));
+		g_free(tmp);
+	}
+}
+
+
+/* Notify message to the client. The notify arguments are sent in the
+   same order as servers sends them. The arguments are same as received
+   from the server except for ID's.  If ID is received application receives
+   the corresponding entry to the ID. For example, if Client ID is received
+   application receives SilcClientEntry.  Also, if the notify type is
+   for channel the channel entry is sent to application (even if server
+   does not send it because client library gets the channel entry from
+   the Channel ID in the packet's header). */
+
+static void
+silc_notify(SilcClient client, SilcClientConnection conn,
+	    SilcNotifyType type, ...)
+{
+	va_list va;
+	PurpleConnection *gc = client->application;
+	SilcPurple sg = gc->proto_data;
+	PurpleConversation *convo;
+	SilcClientEntry client_entry, client_entry2;
+	SilcChannelEntry channel;
+	SilcServerEntry server_entry;
+	SilcIdType idtype;
+	void *entry;
+	SilcUInt32 mode;
+	SilcHashTableList htl;
+	SilcChannelUser chu;
+	char buf[512], buf2[512], *tmp, *name;
+	SilcNotifyType notify;
+	PurpleBuddy *b;
+	int i;
+
+	va_start(va, type);
+	memset(buf, 0, sizeof(buf));
+
+	switch (type) {
+
+	case SILC_NOTIFY_TYPE_NONE:
+		break;
+
+	case SILC_NOTIFY_TYPE_INVITE:
+		{
+			GHashTable *components;
+			va_arg(va, SilcChannelEntry);
+			name = va_arg(va, char *);
+			client_entry = va_arg(va, SilcClientEntry);
+
+			components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+			g_hash_table_insert(components, strdup("channel"), strdup(name));
+			serv_got_chat_invite(gc, name, client_entry->nickname, NULL, components);
+		}
+		break;
+
+	case SILC_NOTIFY_TYPE_JOIN:
+		client_entry = va_arg(va, SilcClientEntry);
+		channel = va_arg(va, SilcChannelEntry);
+
+		/* If we joined channel, do nothing */
+		if (client_entry == conn->local_entry)
+			break;
+
+		convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
+								channel->channel_name, sg->account);
+		if (!convo)
+			break;
+
+		/* Join user to channel */
+		g_snprintf(buf, sizeof(buf), "%s@%s",
+			   client_entry->username, client_entry->hostname);
+		purple_conv_chat_add_user(PURPLE_CONV_CHAT(convo),
+					g_strdup(client_entry->nickname), buf, PURPLE_CBFLAGS_NONE, TRUE);
+
+		break;
+
+	case SILC_NOTIFY_TYPE_LEAVE:
+		client_entry = va_arg(va, SilcClientEntry);
+		channel = va_arg(va, SilcChannelEntry);
+
+		convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
+								channel->channel_name, sg->account);
+		if (!convo)
+			break;
+
+		/* Remove user from channel */
+		purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo),
+					   client_entry->nickname, NULL);
+
+		break;
+
+	case SILC_NOTIFY_TYPE_SIGNOFF:
+		client_entry = va_arg(va, SilcClientEntry);
+		tmp = va_arg(va, char *);
+
+		if (!client_entry->nickname)
+			break;
+
+		/* Remove from all channels */
+		silc_hash_table_list(client_entry->channels, &htl);
+		while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
+			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
+									chu->channel->channel_name, sg->account);
+			if (!convo)
+				continue;
+			purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo),
+						   client_entry->nickname,
+						   tmp);
+		}
+		silc_hash_table_list_reset(&htl);
+
+		break;
+
+	case SILC_NOTIFY_TYPE_TOPIC_SET:
+		{
+			char *esc, *tmp2;
+			idtype = va_arg(va, int);
+			entry = va_arg(va, void *);
+			tmp = va_arg(va, char *);
+			channel = va_arg(va, SilcChannelEntry);
+
+			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
+									channel->channel_name, sg->account);
+			if (!convo)
+				break;
+
+			if (!tmp)
+				break;
+
+			esc = g_markup_escape_text(tmp, -1);
+			tmp2 = purple_markup_linkify(esc);
+			g_free(esc);
+
+			if (idtype == SILC_ID_CLIENT) {
+				client_entry = (SilcClientEntry)entry;
+				g_snprintf(buf, sizeof(buf),
+						_("%s has changed the topic of <I>%s</I> to: %s"),
+						client_entry->nickname, channel->channel_name, tmp2);
+				purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname,
+						buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
+				purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo),
+						client_entry->nickname, tmp);
+			} else if (idtype == SILC_ID_SERVER) {
+				server_entry = (SilcServerEntry)entry;
+				g_snprintf(buf, sizeof(buf),
+						_("%s has changed the topic of <I>%s</I> to: %s"),
+						server_entry->server_name, channel->channel_name, tmp2);
+				purple_conv_chat_write(PURPLE_CONV_CHAT(convo), server_entry->server_name,
+						buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
+				purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo),
+						server_entry->server_name, tmp);
+			} else if (idtype == SILC_ID_CHANNEL) {
+				channel = (SilcChannelEntry)entry;
+				g_snprintf(buf, sizeof(buf),
+						_("%s has changed the topic of <I>%s</I> to: %s"),
+						channel->channel_name, channel->channel_name, tmp2);
+				purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name,
+						buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
+				purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo),
+						channel->channel_name, tmp);
+			} else {
+				purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, tmp);
+			}
+
+			g_free(tmp2);
+
+			break;
+
+		}
+	case SILC_NOTIFY_TYPE_NICK_CHANGE:
+		client_entry = va_arg(va, SilcClientEntry);
+		client_entry2 = va_arg(va, SilcClientEntry);
+
+		if (!strcmp(client_entry->nickname, client_entry2->nickname))
+			break;
+
+		/* Change nick on all channels */
+		silc_hash_table_list(client_entry2->channels, &htl);
+		while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
+			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
+									chu->channel->channel_name, sg->account);
+			if (!convo)
+				continue;
+			if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(convo), client_entry->nickname))
+				purple_conv_chat_rename_user(PURPLE_CONV_CHAT(convo),
+										   client_entry->nickname,
+										   client_entry2->nickname);
+		}
+		silc_hash_table_list_reset(&htl);
+
+		break;
+
+	case SILC_NOTIFY_TYPE_CMODE_CHANGE:
+		idtype = va_arg(va, int);
+		entry = va_arg(va, void *);
+		mode = va_arg(va, SilcUInt32);
+		(void)va_arg(va, char *);
+		(void)va_arg(va, char *);
+		(void)va_arg(va, char *);
+		(void)va_arg(va, SilcPublicKey);
+		(void)va_arg(va, SilcBuffer);
+		channel = va_arg(va, SilcChannelEntry);
+
+		convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
+								channel->channel_name, sg->account);
+		if (!convo)
+			break;
+
+		if (idtype == SILC_ID_CLIENT)
+			name = ((SilcClientEntry)entry)->nickname;
+		else if (idtype == SILC_ID_SERVER)
+			name = ((SilcServerEntry)entry)->server_name;
+		else
+			name = ((SilcChannelEntry)entry)->channel_name;
+		if (!name)
+			break;
+
+		if (mode) {
+			silcpurple_get_chmode_string(mode, buf2, sizeof(buf2));
+			g_snprintf(buf, sizeof(buf),
+				   _("<I>%s</I> set channel <I>%s</I> modes to: %s"), name,
+				   channel->channel_name, buf2);
+		} else {
+			g_snprintf(buf, sizeof(buf),
+				   _("<I>%s</I> removed all channel <I>%s</I> modes"), name,
+				   channel->channel_name);
+		}
+		purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name,
+				     buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
+		break;
+
+	case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
+		{
+			PurpleConvChatBuddyFlags flags = PURPLE_CBFLAGS_NONE;
+			idtype = va_arg(va, int);
+			entry = va_arg(va, void *);
+			mode = va_arg(va, SilcUInt32);
+			client_entry2 = va_arg(va, SilcClientEntry);
+			channel = va_arg(va, SilcChannelEntry);
+
+			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
+									channel->channel_name, sg->account);
+			if (!convo)
+				break;
+
+			if (idtype == SILC_ID_CLIENT)
+				name = ((SilcClientEntry)entry)->nickname;
+			else if (idtype == SILC_ID_SERVER)
+				name = ((SilcServerEntry)entry)->server_name;
+			else
+				name = ((SilcChannelEntry)entry)->channel_name;
+			if (!name)
+				break;
+
+			if (mode) {
+				silcpurple_get_chumode_string(mode, buf2, sizeof(buf2));
+				g_snprintf(buf, sizeof(buf),
+						_("<I>%s</I> set <I>%s's</I> modes to: %s"), name,
+						client_entry2->nickname, buf2);
+				if (mode & SILC_CHANNEL_UMODE_CHANFO)
+					flags |= PURPLE_CBFLAGS_FOUNDER;
+				if (mode & SILC_CHANNEL_UMODE_CHANOP)
+					flags |= PURPLE_CBFLAGS_OP;
+			} else {
+				g_snprintf(buf, sizeof(buf),
+						_("<I>%s</I> removed all <I>%s's</I> modes"), name,
+						client_entry2->nickname);
+			}
+			purple_conv_chat_write(PURPLE_CONV_CHAT(convo), channel->channel_name,
+					buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
+			purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(convo), client_entry2->nickname, flags);
+			break;
+		}
+
+	case SILC_NOTIFY_TYPE_MOTD:
+		tmp = va_arg(va, char *);
+		silc_free(sg->motd);
+		sg->motd = silc_memdup(tmp, strlen(tmp));
+		break;
+
+	case SILC_NOTIFY_TYPE_KICKED:
+		client_entry = va_arg(va, SilcClientEntry);
+		tmp = va_arg(va, char *);
+		client_entry2 = va_arg(va, SilcClientEntry);
+		channel = va_arg(va, SilcChannelEntry);
+
+		convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
+								channel->channel_name, sg->account);
+		if (!convo)
+			break;
+
+		if (client_entry == conn->local_entry) {
+			/* Remove us from channel */
+			g_snprintf(buf, sizeof(buf),
+				   _("You have been kicked off <I>%s</I> by <I>%s</I> (%s)"),
+				   channel->channel_name, client_entry2->nickname,
+				   tmp ? tmp : "");
+			purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname,
+					     buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
+			serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)));
+		} else {
+			/* Remove user from channel */
+			g_snprintf(buf, sizeof(buf), _("Kicked by %s (%s)"),
+				   client_entry2->nickname, tmp ? tmp : "");
+			purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo),
+						   client_entry->nickname,
+						   buf);
+		}
+
+		break;
+
+	case SILC_NOTIFY_TYPE_KILLED:
+		client_entry = va_arg(va, SilcClientEntry);
+		tmp = va_arg(va, char *);
+		idtype = va_arg(va, int);
+		entry = va_arg(va, SilcClientEntry);
+
+		if (!client_entry->nickname)
+			break;
+
+		if (client_entry == conn->local_entry) {
+			if (idtype == SILC_ID_CLIENT) {
+				client_entry2 = (SilcClientEntry)entry;
+				g_snprintf(buf, sizeof(buf),
+					   _("You have been killed by %s (%s)"),
+					   client_entry2->nickname, tmp ? tmp : "");
+			} else if (idtype == SILC_ID_SERVER) {
+				server_entry = (SilcServerEntry)entry;
+				g_snprintf(buf, sizeof(buf),
+					   _("You have been killed by %s (%s)"),
+					   server_entry->server_name, tmp ? tmp : "");
+			} else if (idtype == SILC_ID_CHANNEL) {
+				channel = (SilcChannelEntry)entry;
+				g_snprintf(buf, sizeof(buf),
+					   _("You have been killed by %s (%s)"),
+					   channel->channel_name, tmp ? tmp : "");
+			}
+
+			/* Remove us from all channels */
+			silc_hash_table_list(client_entry->channels, &htl);
+			while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
+				convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
+										chu->channel->channel_name, sg->account);
+				if (!convo)
+					continue;
+				purple_conv_chat_write(PURPLE_CONV_CHAT(convo), client_entry->nickname,
+						     buf, PURPLE_MESSAGE_SYSTEM, time(NULL));
+				serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)));
+			}
+			silc_hash_table_list_reset(&htl);
+
+		} else {
+			if (idtype == SILC_ID_CLIENT) {
+				client_entry2 = (SilcClientEntry)entry;
+				g_snprintf(buf, sizeof(buf),
+					   _("Killed by %s (%s)"),
+					   client_entry2->nickname, tmp ? tmp : "");
+			} else if (idtype == SILC_ID_SERVER) {
+				server_entry = (SilcServerEntry)entry;
+				g_snprintf(buf, sizeof(buf),
+					   _("Killed by %s (%s)"),
+					   server_entry->server_name, tmp ? tmp : "");
+			} else if (idtype == SILC_ID_CHANNEL) {
+				channel = (SilcChannelEntry)entry;
+				g_snprintf(buf, sizeof(buf),
+					   _("Killed by %s (%s)"),
+					   channel->channel_name, tmp ? tmp : "");
+			}
+
+			/* Remove user from all channels */
+			silc_hash_table_list(client_entry->channels, &htl);
+			while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
+				convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
+										chu->channel->channel_name, sg->account);
+				if (!convo)
+					continue;
+				purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo),
+							   client_entry->nickname, tmp);
+			}
+			silc_hash_table_list_reset(&htl);
+		}
+
+		break;
+
+	case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
+		break;
+
+	case SILC_NOTIFY_TYPE_SERVER_SIGNOFF:
+		{
+			int i;
+			SilcClientEntry *clients;
+			SilcUInt32 clients_count;
+
+			(void)va_arg(va, void *);
+			clients = va_arg(va, SilcClientEntry *);
+			clients_count = va_arg(va, SilcUInt32);
+
+			for (i = 0; i < clients_count; i++) {
+				if (!clients[i]->nickname)
+					break;
+
+				/* Remove from all channels */
+				silc_hash_table_list(clients[i]->channels, &htl);
+				while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
+					convo =
+						purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
+											chu->channel->channel_name, sg->account);
+					if (!convo)
+						continue;
+					purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo),
+								   clients[i]->nickname,
+								   _("Server signoff"));
+				}
+				silc_hash_table_list_reset(&htl);
+			}
+		}
+		break;
+
+	case SILC_NOTIFY_TYPE_ERROR:
+		{
+			SilcStatus error = va_arg(va, int);
+			purple_notify_error(gc, "Error Notify",
+					  silc_get_status_message(error),
+					  NULL);
+		}
+		break;
+
+	case SILC_NOTIFY_TYPE_WATCH:
+		{
+			SilcPublicKey public_key;
+			unsigned char *pk;
+			SilcUInt32 pk_len;
+			char *fingerprint;
+
+			client_entry = va_arg(va, SilcClientEntry);
+			(void)va_arg(va, char *);
+			mode = va_arg(va, SilcUInt32);
+			notify = va_arg(va, int);
+			public_key = va_arg(va, SilcPublicKey);
+
+			b = NULL;
+			if (public_key) {
+				PurpleBlistNode *gnode, *cnode, *bnode;
+				const char *f;
+
+				pk = silc_pkcs_public_key_encode(public_key, &pk_len);
+				if (!pk)
+					break;
+				fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
+				for (i = 0; i < strlen(fingerprint); i++)
+					if (fingerprint[i] == ' ')
+						fingerprint[i] = '_';
+				g_snprintf(buf, sizeof(buf) - 1,
+					   "%s" G_DIR_SEPARATOR_S "clientkeys"
+					   G_DIR_SEPARATOR_S "clientkey_%s.pub",
+					   silcpurple_silcdir(), fingerprint);
+				silc_free(fingerprint);
+				silc_free(pk);
+
+				/* Find buddy by associated public key */
+				for (gnode = purple_get_blist()->root; gnode;
+				     gnode = gnode->next) {
+					if (!PURPLE_BLIST_NODE_IS_GROUP(gnode))
+						continue;
+					for (cnode = gnode->child; cnode; cnode = cnode->next) {
+						if( !PURPLE_BLIST_NODE_IS_CONTACT(cnode))
+							continue;
+						for (bnode = cnode->child; bnode;
+						     bnode = bnode->next) {
+							if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode))
+								continue;
+							b = (PurpleBuddy *)bnode;
+							if (b->account != gc->account)
+								continue;
+							f = purple_blist_node_get_string(bnode, "public-key");
+							if (f && !strcmp(f, buf))
+								goto cont;
+							b = NULL;
+						}
+					}
+				}
+			}
+		cont:
+			if (!b) {
+				/* Find buddy by nickname */
+				b = purple_find_buddy(sg->account, client_entry->nickname);
+				if (!b) {
+					purple_debug_warning("silc", "WATCH for %s, unknown buddy",
+						client_entry->nickname);
+					break;
+				}
+			}
+
+			silc_free(b->proto_data);
+			b->proto_data = silc_memdup(client_entry->id,
+						    sizeof(*client_entry->id));
+			if (notify == SILC_NOTIFY_TYPE_NICK_CHANGE) {
+				break;
+			} else if (notify == SILC_NOTIFY_TYPE_UMODE_CHANGE) {
+				/* See if client was away and is now present */
+				if (!(mode & (SILC_UMODE_GONE | SILC_UMODE_INDISPOSED |
+					      SILC_UMODE_BUSY | SILC_UMODE_PAGE |
+					      SILC_UMODE_DETACHED)) &&
+				    (client_entry->mode & SILC_UMODE_GONE ||
+				     client_entry->mode & SILC_UMODE_INDISPOSED ||
+				     client_entry->mode & SILC_UMODE_BUSY ||
+				     client_entry->mode & SILC_UMODE_PAGE ||
+				     client_entry->mode & SILC_UMODE_DETACHED)) {
+					client_entry->mode = mode;
+					purple_prpl_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL);
+				}
+				else if ((mode & SILC_UMODE_GONE) ||
+					 (mode & SILC_UMODE_INDISPOSED) ||
+					 (mode & SILC_UMODE_BUSY) ||
+					 (mode & SILC_UMODE_PAGE) ||
+					 (mode & SILC_UMODE_DETACHED)) {
+					client_entry->mode = mode;
+					purple_prpl_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
+				}
+			} else if (notify == SILC_NOTIFY_TYPE_SIGNOFF ||
+				   notify == SILC_NOTIFY_TYPE_SERVER_SIGNOFF ||
+				   notify == SILC_NOTIFY_TYPE_KILLED) {
+				client_entry->mode = mode;
+				purple_prpl_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
+			} else if (notify == SILC_NOTIFY_TYPE_NONE) {
+				client_entry->mode = mode;
+				purple_prpl_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL);
+			}
+		}
+		break;
+
+	default:
+		purple_debug_info("silc", "Unhandled notification: %d\n", type);
+		break;
+	}
+
+	va_end(va);
+}
+
+
+/* Command handler. This function is called always in the command function.
+   If error occurs it will be called as well. `conn' is the associated
+   client connection. `cmd_context' is the command context that was
+   originally sent to the command. `success' is FALSE if error occurred
+   during command. `command' is the command being processed. It must be
+   noted that this is not reply from server. This is merely called just
+   after application has called the command. Just to tell application
+   that the command really was processed. */
+
+static void
+silc_command(SilcClient client, SilcClientConnection conn,
+	     SilcClientCommandContext cmd_context, bool success,
+	     SilcCommand command, SilcStatus status)
+{
+	PurpleConnection *gc = client->application;
+	SilcPurple sg = gc->proto_data;
+
+	switch (command) {
+
+	case SILC_COMMAND_CMODE:
+		if (cmd_context->argc == 3 &&
+		    !strcmp((char *)cmd_context->argv[2], "+C"))
+			sg->chpk = TRUE;
+		else
+			sg->chpk = FALSE;
+		break;
+
+	default:
+		break;
+	}
+}
+
+#if 0
+static void
+silcpurple_whois_more(SilcClientEntry client_entry, gint id)
+{
+	SilcAttributePayload attr;
+	SilcAttribute attribute;
+	char *buf;
+	GString *s;
+	SilcVCardStruct vcard;
+	int i;
+
+	if (id != 0)
+		return;
+
+	memset(&vcard, 0, sizeof(vcard));
+
+	s = g_string_new("");
+
+	silc_dlist_start(client_entry->attrs);
+	while ((attr = silc_dlist_get(client_entry->attrs)) != SILC_LIST_END) {
+		attribute = silc_attribute_get_attribute(attr);
+		switch (attribute) {
+
+		case SILC_ATTRIBUTE_USER_INFO:
+			if (!silc_attribute_get_object(attr, (void *)&vcard,
+						       sizeof(vcard)))
+				continue;
+			g_string_append_printf(s, "%s:\n\n", _("Personal Information"));
+			if (vcard.full_name)
+				g_string_append_printf(s, "%s:\t\t%s\n",
+						       _("Full Name"),
+						       vcard.full_name);
+			if (vcard.first_name)
+				g_string_append_printf(s, "%s:\t%s\n",
+						       _("First Name"),
+						       vcard.first_name);
+			if (vcard.middle_names)
+				g_string_append_printf(s, "%s:\t%s\n",
+						       _("Middle Name"),
+						       vcard.middle_names);
+			if (vcard.family_name)
+				g_string_append_printf(s, "%s:\t%s\n",
+						       _("Family Name"),
+						       vcard.family_name);
+			if (vcard.nickname)
+				g_string_append_printf(s, "%s:\t\t%s\n",
+						       _("Nickname"),
+						       vcard.nickname);
+			if (vcard.bday)
+				g_string_append_printf(s, "%s:\t\t%s\n",
+						       _("Birth Day"),
+						       vcard.bday);
+			if (vcard.title)
+				g_string_append_printf(s, "%s:\t\t%s\n",
+						       _("Job Title"),
+						       vcard.title);
+			if (vcard.role)
+				g_string_append_printf(s, "%s:\t\t%s\n",
+						       _("Job Role"),
+						       vcard.role);
+			if (vcard.org_name)
+				g_string_append_printf(s, "%s:\t%s\n",
+						       _("Organization"),
+						       vcard.org_name);
+			if (vcard.org_unit)
+				g_string_append_printf(s, "%s:\t\t%s\n",
+						       _("Unit"),
+						       vcard.org_unit);
+			if (vcard.url)
+				g_string_append_printf(s, "%s:\t%s\n",
+						       _("Homepage"),
+						       vcard.url);
+			if (vcard.label)
+				g_string_append_printf(s, "%s:\t%s\n",
+						       _("Address"),
+						       vcard.label);
+			for (i = 0; i < vcard.num_tels; i++) {
+				if (vcard.tels[i].telnum)
+					g_string_append_printf(s, "%s:\t\t\t%s\n",
+							       _("Phone"),
+							       vcard.tels[i].telnum);
+			}
+			for (i = 0; i < vcard.num_emails; i++) {
+				if (vcard.emails[i].address)
+					g_string_append_printf(s, "%s:\t\t%s\n",
+							       _("E-Mail"),
+							       vcard.emails[i].address);
+			}
+			if (vcard.note)
+				g_string_append_printf(s, "\n%s:\t\t%s\n",
+						       _("Note"),
+						       vcard.note);
+			break;
+		}
+	}
+
+	buf = g_string_free(s, FALSE);
+	purple_notify_info(NULL, _("User Information"), _("User Information"),
+			 buf);
+	g_free(buf);
+}
+#endif
+
+/* Command reply handler. This function is called always in the command reply
+   function. If error occurs it will be called as well. Normal scenario
+   is that it will be called after the received command data has been parsed
+   and processed. The function is used to pass the received command data to
+   the application.
+
+   `conn' is the associated client connection. `cmd_payload' is the command
+   payload data received from server and it can be ignored. It is provided
+   if the application would like to re-parse the received command data,
+   however, it must be noted that the data is parsed already by the library
+   thus the payload can be ignored. `success' is FALSE if error occurred.
+   In this case arguments are not sent to the application. The `status' is
+   the command reply status server returned. The `command' is the command
+   reply being processed. The function has variable argument list and each
+   command defines the number and type of arguments it passes to the
+   application (on error they are not sent). */
+
+static void
+silc_command_reply(SilcClient client, SilcClientConnection conn,
+		   SilcCommandPayload cmd_payload, bool success,
+		   SilcCommand command, SilcStatus status, ...)
+{
+	PurpleConnection *gc = client->application;
+	SilcPurple sg = gc->proto_data;
+	PurpleConversation *convo;
+	va_list vp;
+
+	va_start(vp, status);
+
+	switch (command) {
+	case SILC_COMMAND_JOIN:
+		{
+			SilcChannelEntry channel_entry;
+
+			if (!success) {
+				purple_notify_error(gc, _("Join Chat"), _("Cannot join channel"),
+						  silc_get_status_message(status));
+				return;
+			}
+
+			(void)va_arg(vp, char *);
+			channel_entry = va_arg(vp, SilcChannelEntry);
+
+			/* Resolve users on channel */
+			silc_client_get_clients_by_channel(client, conn, channel_entry,
+							   silcpurple_chat_join_done,
+							   channel_entry);
+		}
+		break;
+
+	case SILC_COMMAND_LEAVE:
+		break;
+
+	case SILC_COMMAND_USERS:
+		break;
+
+	case SILC_COMMAND_WHOIS:
+		{
+			SilcUInt32 idle, mode;
+			SilcBuffer channels, user_modes;
+			SilcClientEntry client_entry;
+			char tmp[1024], *tmp2;
+			char *moodstr, *statusstr, *contactstr, *langstr, *devicestr, *tzstr, *geostr;
+			PurpleNotifyUserInfo *user_info;
+
+			if (!success) {
+				purple_notify_error(gc, _("User Information"),
+						_("Cannot get user information"),
+						silc_get_status_message(status));
+				break;
+			}
+
+			client_entry = va_arg(vp, SilcClientEntry);
+			if (!client_entry->nickname)
+				break;
+			(void)va_arg(vp, char *);
+			(void)va_arg(vp, char *);
+			(void)va_arg(vp, char *);
+			channels = va_arg(vp, SilcBuffer);
+			mode = va_arg(vp, SilcUInt32);
+			idle = va_arg(vp, SilcUInt32);
+			(void)va_arg(vp, unsigned char *);
+			user_modes = va_arg(vp, SilcBuffer);
+
+			user_info = purple_notify_user_info_new();
+			tmp2 = g_markup_escape_text(client_entry->nickname, -1);
+			purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp2);
+			g_free(tmp2);
+			if (client_entry->realname) {
+				tmp2 = g_markup_escape_text(client_entry->realname, -1);
+				purple_notify_user_info_add_pair(user_info, _("Real Name"), tmp2);
+				g_free(tmp2);
+			}
+			if (client_entry->username) {
+				tmp2 = g_markup_escape_text(client_entry->username, -1);
+				if (client_entry->hostname) {
+					gchar *tmp3;
+					tmp3 = g_strdup_printf("%s@%s", tmp2, client_entry->hostname);
+					purple_notify_user_info_add_pair(user_info, _("Username"), tmp3);
+					g_free(tmp3);
+				} else
+					purple_notify_user_info_add_pair(user_info, _("Username"), tmp2);
+				g_free(tmp2);
+			}
+
+			if (client_entry->mode) {
+				memset(tmp, 0, sizeof(tmp));
+				silcpurple_get_umode_string(client_entry->mode,
+						tmp, sizeof(tmp) - strlen(tmp));
+				purple_notify_user_info_add_pair(user_info, _("User Modes"), tmp);
+			}
+
+			silcpurple_parse_attrs(client_entry->attrs, &moodstr, &statusstr, &contactstr, &langstr, &devicestr, &tzstr, &geostr);
+			if (moodstr) {
+				purple_notify_user_info_add_pair(user_info, _("Mood"), moodstr);
+				g_free(moodstr);
+			}
+
+			if (statusstr) {
+				tmp2 = g_markup_escape_text(statusstr, -1);
+				purple_notify_user_info_add_pair(user_info, _("Status Text"), tmp2);
+				g_free(statusstr);
+				g_free(tmp2);
+			}
+
+			if (contactstr) {
+				purple_notify_user_info_add_pair(user_info, _("Preferred Contact"), contactstr);
+				g_free(contactstr);
+			}
+
+			if (langstr) {
+				purple_notify_user_info_add_pair(user_info, _("Preferred Language"), langstr);
+				g_free(langstr);
+			}
+
+			if (devicestr) {
+				purple_notify_user_info_add_pair(user_info, _("Device"), devicestr);
+				g_free(devicestr);
+			}
+
+			if (tzstr) {
+				purple_notify_user_info_add_pair(user_info, _("Timezone"), tzstr);
+				g_free(tzstr);
+			}
+
+			if (geostr) {
+				purple_notify_user_info_add_pair(user_info, _("Geolocation"), geostr);
+				g_free(geostr);
+			}
+
+			if (client_entry->server)
+				purple_notify_user_info_add_pair(user_info, _("Server"), client_entry->server);
+
+			if (channels && user_modes) {
+				SilcUInt32 *umodes;
+				SilcDList list =
+					silc_channel_payload_parse_list(channels->data,
+							channels->len);
+				if (list && silc_get_mode_list(user_modes,
+							silc_dlist_count(list),
+							&umodes)) {
+					SilcChannelPayload entry;
+					int i = 0;
+
+					memset(tmp, 0, sizeof(tmp));
+					silc_dlist_start(list);
+					while ((entry = silc_dlist_get(list))
+							!= SILC_LIST_END) {
+						SilcUInt32 name_len;
+						char *m = silc_client_chumode_char(umodes[i++]);
+						char *name = (char *)silc_channel_get_name(entry, &name_len);
+						if (m)
+							silc_strncat(tmp, sizeof(tmp) - 1, m, strlen(m));
+						silc_strncat(tmp, sizeof(tmp) - 1, name, name_len);
+						silc_strncat(tmp, sizeof(tmp) - 1, "  ", 1);
+						silc_free(m);
+
+					}
+					tmp2 = g_markup_escape_text(tmp, -1);
+					purple_notify_user_info_add_pair(user_info, _("Currently on"), tmp2);
+					g_free(tmp2);
+					silc_free(umodes);
+				}
+			}
+
+			if (client_entry->public_key) {
+				char *fingerprint, *babbleprint;
+				unsigned char *pk;
+				SilcUInt32 pk_len;
+				pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len);
+				fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
+				babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
+				purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint);
+				purple_notify_user_info_add_pair(user_info, _("Public Key Babbleprint"), babbleprint);
+				silc_free(fingerprint);
+				silc_free(babbleprint);
+				silc_free(pk);
+			}
+
+#if 0 /* XXX for now, let's not show attrs here */
+			if (client_entry->attrs)
+				purple_request_action(gc, _("User Information"),
+						_("User Information"),
+						buf, 1, client_entry, 2,
+						_("OK"), G_CALLBACK(silcpurple_whois_more),
+						_("_More..."), G_CALLBACK(silcpurple_whois_more), gc->account, NULL, NULL);
+			else
+#endif
+			purple_notify_userinfo(gc, client_entry->nickname, user_info, NULL, NULL);
+			purple_notify_user_info_destroy(user_info);
+		}
+		break;
+
+	case SILC_COMMAND_WHOWAS:
+		{
+			SilcClientEntry client_entry;
+			char *nickname, *realname, *username, *tmp;
+			PurpleNotifyUserInfo *user_info;
+
+			if (!success) {
+				purple_notify_error(gc, _("User Information"),
+						  _("Cannot get user information"),
+						  silc_get_status_message(status));
+				break;
+			}
+
+			client_entry = va_arg(vp, SilcClientEntry);
+			nickname = va_arg(vp, char *);
+			username = va_arg(vp, char *);
+			realname = va_arg(vp, char *);
+			if (!nickname)
+				break;
+
+			user_info = purple_notify_user_info_new();
+			tmp = g_markup_escape_text(nickname, -1);
+			purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp);
+			g_free(tmp);
+			if (realname) {
+				tmp = g_markup_escape_text(realname, -1);
+				purple_notify_user_info_add_pair(user_info, _("Real Name"), tmp);
+				g_free(tmp);
+			}
+			if (username) {
+				tmp = g_markup_escape_text(username, -1);
+				if (client_entry && client_entry->hostname) {
+					gchar *tmp3;
+					tmp3 = g_strdup_printf("%s@%s", tmp, client_entry->hostname);
+					purple_notify_user_info_add_pair(user_info, _("Username"), tmp3);
+					g_free(tmp3);
+				} else
+					purple_notify_user_info_add_pair(user_info, _("Username"), tmp);
+				g_free(tmp);
+			}
+			if (client_entry && client_entry->server)
+				purple_notify_user_info_add_pair(user_info, _("Server"), client_entry->server);
+
+
+			if (client_entry && client_entry->public_key) {
+				char *fingerprint, *babbleprint;
+				unsigned char *pk;
+				SilcUInt32 pk_len;
+				pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len);
+				fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
+				babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
+				purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint);
+				purple_notify_user_info_add_pair(user_info, _("Public Key Babbleprint"), babbleprint);
+				silc_free(fingerprint);
+				silc_free(babbleprint);
+				silc_free(pk);
+			}
+
+			purple_notify_userinfo(gc, nickname, user_info, NULL, NULL);
+			purple_notify_user_info_destroy(user_info);
+		}
+		break;
+
+	case SILC_COMMAND_DETACH:
+		if (!success) {
+			purple_notify_error(gc, _("Detach From Server"), _("Cannot detach"),
+					  silc_get_status_message(status));
+			return;
+		}
+		break;
+
+	case SILC_COMMAND_TOPIC:
+		{
+			SilcChannelEntry channel;
+
+			if (!success) {
+				purple_notify_error(gc, _("Topic"), _("Cannot set topic"),
+						  silc_get_status_message(status));
+				return;
+			}
+
+			channel = va_arg(vp, SilcChannelEntry);
+
+			convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
+									channel->channel_name, sg->account);
+			if (!convo) {
+				purple_debug_error("silc", "Got a topic for %s, which doesn't exist\n",
+								 channel->channel_name);
+				break;
+			}
+
+			/* Set topic */
+			if (channel->topic)
+				purple_conv_chat_set_topic(PURPLE_CONV_CHAT(convo), NULL, channel->topic);
+		}
+		break;
+
+	case SILC_COMMAND_NICK:
+		{
+			/* I don't think we should need to do this because the server should
+			 * be sending a SILC_NOTIFY_TYPE_NICK_CHANGE when we change our own
+			 * nick, but it isn't, so we deal with it here instead. Stu. */
+			SilcClientEntry local_entry;
+			SilcHashTableList htl;
+			SilcChannelUser chu;
+			const char *oldnick;
+
+			if (!success) {
+				purple_notify_error(gc, _("Nick"), _("Failed to change nickname"),
+						silc_get_status_message(status));
+				return;
+			}
+
+			local_entry = va_arg(vp, SilcClientEntry);
+
+			/* Change nick on all channels */
+			silc_hash_table_list(local_entry->channels, &htl);
+			while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
+				convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
+									chu->channel->channel_name, sg->account);
+				if (!convo)
+					continue;
+				oldnick = purple_conv_chat_get_nick(PURPLE_CONV_CHAT(convo));
+				if (strcmp(oldnick, purple_normalize(purple_conversation_get_account(convo), local_entry->nickname))) {
+					purple_conv_chat_rename_user(PURPLE_CONV_CHAT(convo),
+							oldnick, local_entry->nickname);
+					purple_conv_chat_set_nick(PURPLE_CONV_CHAT(convo), local_entry->nickname);
+				}
+			}
+			silc_hash_table_list_reset(&htl);
+
+			purple_connection_set_display_name(gc, local_entry->nickname);
+		}
+		break;
+
+	case SILC_COMMAND_LIST:
+		{
+			char *topic, *name;
+			int usercount;
+			PurpleRoomlistRoom *room;
+
+			if (sg->roomlist_canceled)
+				break;
+
+			if (!success) {
+				purple_notify_error(gc, _("Error"), _("Error retrieving room list"),
+						  silc_get_status_message(status));
+				purple_roomlist_set_in_progress(sg->roomlist, FALSE);
+				purple_roomlist_unref(sg->roomlist);
+				sg->roomlist = NULL;
+				return;
+			}
+
+			(void)va_arg(vp, SilcChannelEntry);
+			name = va_arg(vp, char *);
+			if (!name) {
+				purple_notify_error(gc, _("Roomlist"), _("Cannot get room list"),
+						  silc_get_status_message(status));
+				purple_roomlist_set_in_progress(sg->roomlist, FALSE);
+				purple_roomlist_unref(sg->roomlist);
+				sg->roomlist = NULL;
+				return;
+			}
+			topic = va_arg(vp, char *);
+			usercount = va_arg(vp, int);
+
+			room = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM, name, NULL);
+			purple_roomlist_room_add_field(sg->roomlist, room, name);
+			purple_roomlist_room_add_field(sg->roomlist, room,
+						     SILC_32_TO_PTR(usercount));
+			purple_roomlist_room_add_field(sg->roomlist, room,
+						     topic ? topic : "");
+			purple_roomlist_room_add(sg->roomlist, room);
+
+			if (status == SILC_STATUS_LIST_END ||
+			    status == SILC_STATUS_OK) {
+				purple_roomlist_set_in_progress(sg->roomlist, FALSE);
+				purple_roomlist_unref(sg->roomlist);
+				sg->roomlist = NULL;
+			}
+		}
+		break;
+
+	case SILC_COMMAND_GETKEY:
+		{
+			SilcPublicKey public_key;
+
+			if (!success) {
+				purple_notify_error(gc, _("Get Public Key"),
+						  _("Cannot fetch the public key"),
+						  silc_get_status_message(status));
+				return;
+			}
+
+			(void)va_arg(vp, SilcUInt32);
+			(void)va_arg(vp, void *);
+			public_key = va_arg(vp, SilcPublicKey);
+
+			if (!public_key)
+				purple_notify_error(gc, _("Get Public Key"),
+						  _("Cannot fetch the public key"),
+						  _("No public key was received"));
+		}
+		break;
+
+	case SILC_COMMAND_INFO:
+		{
+
+			char *server_name;
+			char *server_info;
+			char tmp[256];
+
+			if (!success) {
+				purple_notify_error(gc, _("Server Information"),
+						  _("Cannot get server information"),
+						  silc_get_status_message(status));
+				return;
+			}
+
+			(void)va_arg(vp, SilcServerEntry);
+			server_name = va_arg(vp, char *);
+			server_info = va_arg(vp, char *);
+
+			if (server_name && server_info) {
+				g_snprintf(tmp, sizeof(tmp), "Server: %s\n%s",
+					   server_name, server_info);
+				purple_notify_info(gc, NULL, _("Server Information"), tmp);
+			}
+		}
+		break;
+
+	case SILC_COMMAND_STATS:
+		{
+			SilcUInt32 starttime, uptime, my_clients, my_channels, my_server_ops,
+			my_router_ops, cell_clients, cell_channels, cell_servers,
+			clients, channels, servers, routers, server_ops, router_ops;
+			SilcUInt32 buffer_length;
+			SilcBufferStruct buf;
+
+			unsigned char *server_stats;
+			char *msg;
+
+			if (!success) {
+				purple_notify_error(gc, _("Server Statistics"),
+						_("Cannot get server statistics"),
+						silc_get_status_message(status));
+				return;
+			}
+
+			server_stats = va_arg(vp, unsigned char *);
+			buffer_length = va_arg(vp, SilcUInt32);
+			if (!server_stats || !buffer_length) {
+				purple_notify_error(gc, _("Server Statistics"),
+						_("No server statistics available"), NULL);
+				break;
+			}
+			silc_buffer_set(&buf, server_stats, buffer_length);
+			silc_buffer_unformat(&buf,
+					SILC_STR_UI_INT(&starttime),
+					SILC_STR_UI_INT(&uptime),
+					SILC_STR_UI_INT(&my_clients),
+					SILC_STR_UI_INT(&my_channels),
+					SILC_STR_UI_INT(&my_server_ops),
+					SILC_STR_UI_INT(&my_router_ops),
+					SILC_STR_UI_INT(&cell_clients),
+					SILC_STR_UI_INT(&cell_channels),
+					SILC_STR_UI_INT(&cell_servers),
+					SILC_STR_UI_INT(&clients),
+					SILC_STR_UI_INT(&channels),
+					SILC_STR_UI_INT(&servers),
+					SILC_STR_UI_INT(&routers),
+					SILC_STR_UI_INT(&server_ops),
+					SILC_STR_UI_INT(&router_ops),
+					SILC_STR_END);
+
+			msg = g_strdup_printf(_("Local server start time: %s\n"
+					"Local server uptime: %s\n"
+					"Local server clients: %d\n"
+					"Local server channels: %d\n"
+					"Local server operators: %d\n"
+					"Local router operators: %d\n"
+					"Local cell clients: %d\n"
+					"Local cell channels: %d\n"
+					"Local cell servers: %d\n"
+					"Total clients: %d\n"
+					"Total channels: %d\n"
+					"Total servers: %d\n"
+					"Total routers: %d\n"
+					"Total server operators: %d\n"
+					"Total router operators: %d\n"),
+					silc_get_time(starttime),
+					purple_str_seconds_to_string((int)uptime),
+					(int)my_clients, (int)my_channels, (int)my_server_ops, (int)my_router_ops,
+					(int)cell_clients, (int)cell_channels, (int)cell_servers,
+					(int)clients, (int)channels, (int)servers, (int)routers,
+					(int)server_ops, (int)router_ops);
+
+			purple_notify_info(gc, NULL,
+					_("Network Statistics"), msg);
+			g_free(msg);
+		}
+		break;
+
+	case SILC_COMMAND_PING:
+		{
+			if (!success) {
+				purple_notify_error(gc, _("Ping"), _("Ping failed"),
+								  silc_get_status_message(status));
+				return;
+			}
+
+			purple_notify_info(gc, _("Ping"), _("Ping reply received from server"),
+							 NULL);
+		}
+		break;
+
+	case SILC_COMMAND_KILL:
+		if (!success) {
+			purple_notify_error(gc, _("Kill User"),
+					  _("Could not kill user"),
+					  silc_get_status_message(status));
+			return;
+		}
+		break;
+
+	case SILC_COMMAND_CMODE:
+		{
+			SilcChannelEntry channel_entry;
+			SilcBuffer channel_pubkeys;
+
+			if (!success)
+				return;
+
+			channel_entry = va_arg(vp, SilcChannelEntry);
+			(void)va_arg(vp, SilcUInt32);
+			(void)va_arg(vp, SilcPublicKey);
+			channel_pubkeys = va_arg(vp, SilcBuffer);
+
+			if (sg->chpk)
+				silcpurple_chat_chauth_show(sg, channel_entry, channel_pubkeys);
+		}
+		break;
+
+	default:
+		if (success)
+			purple_debug_info("silc", "Unhandled command: %d (succeeded)\n", command);
+		else
+			purple_debug_info("silc", "Unhandled command: %d (failed: %s)\n", command,
+							silc_get_status_message(status));
+		break;
+	}
+
+	va_end(vp);
+}
+
+
+/* Called to indicate that connection was either successfully established
+   or connecting failed.  This is also the first time application receives
+   the SilcClientConnection object which it should save somewhere.
+   If the `success' is FALSE the application must always call the function
+   silc_client_close_connection. */
+
+static void
+silc_connected(SilcClient client, SilcClientConnection conn,
+	       SilcClientConnectionStatus status)
+{
+	PurpleConnection *gc = client->application;
+	SilcPurple sg;
+
+	if (gc == NULL) {
+		silc_client_close_connection(client, conn);
+		return;
+	}
+	sg = gc->proto_data;
+
+	switch (status) {
+	case SILC_CLIENT_CONN_SUCCESS:
+	case SILC_CLIENT_CONN_SUCCESS_RESUME:
+		purple_connection_set_state(gc, PURPLE_CONNECTED);
+
+		/* Send the server our buddy list */
+		silcpurple_send_buddylist(gc);
+
+		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
+
+		/* Send any UMODEs configured for account */
+		if (purple_account_get_bool(sg->account, "block-ims", FALSE)) {
+			silc_client_command_call(sg->client, sg->conn, NULL,
+					"UMODE", "+P", NULL);
+		}
+
+		return;
+		break;
+	case SILC_CLIENT_CONN_ERROR:
+		purple_connection_error(gc, _("Error during connecting to SILC Server"));
+		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
+		break;
+
+	case SILC_CLIENT_CONN_ERROR_KE:
+		purple_connection_error(gc, _("Key Exchange failed"));
+		break;
+
+	case SILC_CLIENT_CONN_ERROR_AUTH:
+		purple_connection_error(gc, _("Authentication failed"));
+		break;
+
+	case SILC_CLIENT_CONN_ERROR_RESUME:
+		purple_connection_error(gc,
+				      _("Resuming detached session failed. "
+					"Press Reconnect to create new connection."));
+		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
+		break;
+
+	case SILC_CLIENT_CONN_ERROR_TIMEOUT:
+		purple_connection_error(gc, _("Connection Timeout"));
+		break;
+	}
+
+	/* Error */
+	sg->conn = NULL;
+	silc_client_close_connection(client, conn);
+}
+
+
+/* Called to indicate that connection was disconnected to the server.
+   The `status' may tell the reason of the disconnection, and if the
+   `message' is non-NULL it may include the disconnection message
+   received from server. */
+
+static void
+silc_disconnected(SilcClient client, SilcClientConnection conn,
+		  SilcStatus status, const char *message)
+{
+	PurpleConnection *gc = client->application;
+	SilcPurple sg = gc->proto_data;
+
+	if (sg->resuming && !sg->detaching)
+		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
+
+	sg->conn = NULL;
+
+	/* Close the connection */
+	if (!sg->detaching)
+		purple_connection_error(gc, _("Disconnected by server"));
+	else
+		/* TODO: Does this work correctly? Maybe we need to set wants_to_die? */
+		purple_account_disconnect(purple_connection_get_account(gc));
+}
+
+
+typedef struct {
+	SilcGetAuthMeth completion;
+	void *context;
+} *SilcPurpleGetAuthMethod;
+
+/* Callback called when we've received the authentication method information
+   from the server after we've requested it. */
+
+static void silc_get_auth_method_callback(SilcClient client,
+					  SilcClientConnection conn,
+					  SilcAuthMethod auth_meth,
+					  void *context)
+{
+	SilcPurpleGetAuthMethod internal = context;
+
+	switch (auth_meth) {
+	case SILC_AUTH_NONE:
+		/* No authentication required. */
+		(*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
+		break;
+
+	case SILC_AUTH_PASSWORD:
+		/* By returning NULL here the library will ask the passphrase from us
+		   by calling the silc_ask_passphrase. */
+		(*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
+		break;
+
+	case SILC_AUTH_PUBLIC_KEY:
+		/* Do not get the authentication data now, the library will generate
+		   it using our default key, if we do not provide it here. */
+		(*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context);
+		break;
+	}
+
+	silc_free(internal);
+}
+
+/* Find authentication method and authentication data by hostname and
+   port. The hostname may be IP address as well. When the authentication
+   method has been resolved the `completion' callback with the found
+   authentication method and authentication data is called. The `conn'
+   may be NULL. */
+
+static void
+silc_get_auth_method(SilcClient client, SilcClientConnection conn,
+		     char *hostname, SilcUInt16 port,
+		     SilcGetAuthMeth completion, void *context)
+{
+	PurpleConnection *gc = client->application;
+	SilcPurple sg = gc->proto_data;
+	SilcPurpleGetAuthMethod internal;
+	const char *password;
+
+	/* Progress */
+	if (sg->resuming)
+		purple_connection_update_progress(gc, _("Resuming session"), 4, 5);
+	else
+		purple_connection_update_progress(gc, _("Authenticating connection"), 4, 5);
+
+	/* Check configuration if we have this connection configured.  If we
+	   have then return that data immediately, as it's faster way. */
+	if (purple_account_get_bool(sg->account, "pubkey-auth", FALSE)) {
+		completion(TRUE, SILC_AUTH_PUBLIC_KEY, NULL, 0, context);
+		return;
+	}
+	password = purple_connection_get_password(gc);
+	if (password && *password) {
+		completion(TRUE, SILC_AUTH_PASSWORD, (unsigned char *)password, strlen(password), context);
+		return;
+	}
+
+	/* Resolve the authentication method from server, as we may not know it. */
+	internal = silc_calloc(1, sizeof(*internal));
+	if (!internal)
+		return;
+	internal->completion = completion;
+	internal->context = context;
+	silc_client_request_authentication_method(client, conn,
+						  silc_get_auth_method_callback,
+						  internal);
+}
+
+
+/* Verifies received public key. The `conn_type' indicates which entity
+   (server, client etc.) has sent the public key. If user decides to trust
+   the application may save the key as trusted public key for later
+   use. The `completion' must be called after the public key has been
+   verified. */
+
+static void
+silc_verify_public_key(SilcClient client, SilcClientConnection conn,
+		       SilcSocketType conn_type, unsigned char *pk,
+		       SilcUInt32 pk_len, SilcSKEPKType pk_type,
+		       SilcVerifyPublicKey completion, void *context)
+{
+	PurpleConnection *gc = client->application;
+	SilcPurple sg = gc->proto_data;
+
+	if (!sg->conn && (conn_type == SILC_SOCKET_TYPE_SERVER ||
+			  conn_type == SILC_SOCKET_TYPE_ROUTER)) {
+		/* Progress */
+		if (sg->resuming)
+			purple_connection_update_progress(gc, _("Resuming session"), 3, 5);
+		else
+			purple_connection_update_progress(gc, _("Verifying server public key"),
+							3, 5);
+	}
+
+	/* Verify public key */
+	silcpurple_verify_public_key(client, conn, NULL, conn_type, pk,
+				   pk_len, pk_type, completion, context);
+}
+
+typedef struct {
+	SilcAskPassphrase completion;
+	void *context;
+} *SilcPurpleAskPassphrase;
+
+static void
+silc_ask_passphrase_cb(SilcPurpleAskPassphrase internal, const char *passphrase)
+{
+	if (!passphrase || !(*passphrase))
+		internal->completion(NULL, 0, internal->context);
+	else
+		internal->completion((unsigned char *)passphrase,
+				     strlen(passphrase), internal->context);
+	silc_free(internal);
+}
+
+/* Ask (interact, that is) a passphrase from user. The passphrase is
+   returned to the library by calling the `completion' callback with
+   the `context'. The returned passphrase SHOULD be in UTF-8 encoded,
+   if not then the library will attempt to encode. */
+
+static void
+silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
+		    SilcAskPassphrase completion, void *context)
+{
+	PurpleConnection *gc = client->application;
+	SilcPurpleAskPassphrase internal = silc_calloc(1, sizeof(*internal));
+
+	if (!internal)
+		return;
+	internal->completion = completion;
+	internal->context = context;
+	purple_request_input(gc, _("Passphrase"), NULL,
+			   _("Passphrase required"), NULL, FALSE, TRUE, NULL,
+			   _("OK"), G_CALLBACK(silc_ask_passphrase_cb),
+			   _("Cancel"), G_CALLBACK(silc_ask_passphrase_cb),
+			   purple_connection_get_account(gc), NULL, NULL, internal);
+}
+
+
+/* Notifies application that failure packet was received.  This is called
+   if there is some protocol active in the client.  The `protocol' is the
+   protocol context.  The `failure' is opaque pointer to the failure
+   indication.  Note, that the `failure' is protocol dependant and
+   application must explicitly cast it to correct type.  Usually `failure'
+   is 32 bit failure type (see protocol specs for all protocol failure
+   types). */
+
+static void
+silc_failure(SilcClient client, SilcClientConnection conn,
+	     SilcProtocol protocol, void *failure)
+{
+	PurpleConnection *gc = client->application;
+	char buf[128];
+
+	memset(buf, 0, sizeof(buf));
+
+	if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) {
+		SilcSKEStatus status = (SilcSKEStatus)SILC_PTR_TO_32(failure);
+
+		if (status == SILC_SKE_STATUS_BAD_VERSION)
+			g_snprintf(buf, sizeof(buf),
+				   _("Failure: Version mismatch, upgrade your client"));
+		if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY)
+			g_snprintf(buf, sizeof(buf),
+				   _("Failure: Remote does not trust/support your public key"));
+		if (status == SILC_SKE_STATUS_UNKNOWN_GROUP)
+			g_snprintf(buf, sizeof(buf),
+				   _("Failure: Remote does not support proposed KE group"));
+		if (status == SILC_SKE_STATUS_UNKNOWN_CIPHER)
+			g_snprintf(buf, sizeof(buf),
+				   _("Failure: Remote does not support proposed cipher"));
+		if (status == SILC_SKE_STATUS_UNKNOWN_PKCS)
+			g_snprintf(buf, sizeof(buf),
+				   _("Failure: Remote does not support proposed PKCS"));
+		if (status == SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION)
+			g_snprintf(buf, sizeof(buf),
+				   _("Failure: Remote does not support proposed hash function"));
+		if (status == SILC_SKE_STATUS_UNKNOWN_HMAC)
+			g_snprintf(buf, sizeof(buf),
+				   _("Failure: Remote does not support proposed HMAC"));
+		if (status == SILC_SKE_STATUS_INCORRECT_SIGNATURE)
+			g_snprintf(buf, sizeof(buf), _("Failure: Incorrect signature"));
+		if (status == SILC_SKE_STATUS_INVALID_COOKIE)
+			g_snprintf(buf, sizeof(buf), _("Failure: Invalid cookie"));
+
+		/* Show the error on the progress bar.  A more generic error message
+		   is going to be showed to user after this in the silc_connected. */
+		purple_connection_update_progress(gc, buf, 2, 5);
+	}
+
+	if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) {
+		SilcUInt32 err = SILC_PTR_TO_32(failure);
+
+		if (err == SILC_AUTH_FAILED)
+			g_snprintf(buf, sizeof(buf), _("Failure: Authentication failed"));
+
+		/* Show the error on the progress bar.  A more generic error message
+		   is going to be showed to user after this in the silc_connected. */
+		purple_connection_update_progress(gc, buf, 4, 5);
+	}
+}
+
+/* Asks whether the user would like to perform the key agreement protocol.
+   This is called after we have received an key agreement packet or an
+   reply to our key agreement packet. This returns TRUE if the user wants
+   the library to perform the key agreement protocol and FALSE if it is not
+   desired (application may start it later by calling the function
+   silc_client_perform_key_agreement). If TRUE is returned also the
+   `completion' and `context' arguments must be set by the application. */
+
+static bool
+silc_key_agreement(SilcClient client, SilcClientConnection conn,
+		   SilcClientEntry client_entry, const char *hostname,
+		   SilcUInt16 port, SilcKeyAgreementCallback *completion,
+		   void **context)
+{
+	silcpurple_buddy_keyagr_request(client, conn, client_entry, hostname, port);
+	*completion = NULL;
+	*context = NULL;
+	return FALSE;
+}
+
+
+/* Notifies application that file transfer protocol session is being
+   requested by the remote client indicated by the `client_entry' from
+   the `hostname' and `port'. The `session_id' is the file transfer
+   session and it can be used to either accept or reject the file
+   transfer request, by calling the silc_client_file_receive or
+   silc_client_file_close, respectively. */
+
+static void
+silc_ftp(SilcClient client, SilcClientConnection conn,
+	 SilcClientEntry client_entry, SilcUInt32 session_id,
+	 const char *hostname, SilcUInt16 port)
+{
+	silcpurple_ftp_request(client, conn, client_entry, session_id,
+			     hostname, port);
+}
+
+
+/* Delivers SILC session detachment data indicated by `detach_data' to the
+   application.  If application has issued SILC_COMMAND_DETACH command
+   the client session in the SILC network is not quit.  The client remains
+   in the network but is detached.  The detachment data may be used later
+   to resume the session in the SILC Network.  The appliation is
+   responsible of saving the `detach_data', to for example in a file.
+
+   The detachment data can be given as argument to the functions
+   silc_client_connect_to_server, or silc_client_add_connection when
+   creating connection to remote server, inside SilcClientConnectionParams
+   structure.  If it is provided the client library will attempt to resume
+   the session in the network.  After the connection is created
+   successfully, the application is responsible of setting the user
+   interface for user into the same state it was before detaching (showing
+   same channels, channel modes, etc).  It can do this by fetching the
+   information (like joined channels) from the client library. */
+
+static void
+silc_detach(SilcClient client, SilcClientConnection conn,
+	    const unsigned char *detach_data, SilcUInt32 detach_data_len)
+{
+	PurpleConnection *gc = client->application;
+	SilcPurple sg = gc->proto_data;
+	const char *file;
+
+	/* Save the detachment data to file. */
+	file = silcpurple_session_file(purple_account_get_username(sg->account));
+	g_unlink(file);
+	silc_file_writefile(file, (char *)detach_data, detach_data_len);
+}
+
+SilcClientOperations ops = {
+	silc_say,
+	silc_channel_message,
+	silc_private_message,
+	silc_notify,
+	silc_command,
+	silc_command_reply,
+	silc_connected,
+	silc_disconnected,
+	silc_get_auth_method,
+	silc_verify_public_key,
+	silc_ask_passphrase,
+	silc_failure,
+	silc_key_agreement,
+	silc_ftp,
+	silc_detach
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/silc10/pk.c	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,274 @@
+/*
+
+  silcpurple_pk.c
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2004 Pekka Riikonen
+
+  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; version 2 of the License.
+
+  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.
+
+*/
+
+#include "silcincludes.h"
+#include "silcclient.h"
+#include "silcpurple.h"
+
+/************************* Public Key Verification ***************************/
+
+typedef struct {
+	SilcClient client;
+	SilcClientConnection conn;
+	char *filename;
+	char *entity;
+	char *entity_name;
+	char *fingerprint;
+	char *babbleprint;
+	unsigned char *pk;
+	SilcUInt32 pk_len;
+	SilcSKEPKType pk_type;
+	SilcVerifyPublicKey completion;
+	void *context;
+	gboolean changed;
+} *PublicKeyVerify;
+
+static void silcpurple_verify_ask(const char *entity,
+				const char *fingerprint,
+				const char *babbleprint,
+				PublicKeyVerify verify);
+
+static void silcpurple_verify_cb(PublicKeyVerify verify, gint id)
+{
+	if (id != 2) {
+		if (verify->completion)
+			verify->completion(FALSE, verify->context);
+	} else {
+		if (verify->completion)
+			verify->completion(TRUE, verify->context);
+
+		/* Save the key for future checking */
+		silc_pkcs_save_public_key_data(verify->filename, verify->pk,
+					       verify->pk_len, SILC_PKCS_FILE_PEM);
+	}
+
+	silc_free(verify->filename);
+	silc_free(verify->entity);
+	silc_free(verify->entity_name);
+	silc_free(verify->fingerprint);
+	silc_free(verify->babbleprint);
+	silc_free(verify->pk);
+	silc_free(verify);
+}
+
+static void silcpurple_verify_details_cb(PublicKeyVerify verify)
+{
+	/* What a hack.  We have to display the accept dialog _again_
+	   because Purple closes the dialog after you press the button.  Purple
+	   should have option for the dialogs whether the buttons close them
+	   or not. */
+	silcpurple_verify_ask(verify->entity, verify->fingerprint,
+			    verify->babbleprint, verify);
+}
+
+static void silcpurple_verify_details(PublicKeyVerify verify, gint id)
+{
+	SilcPublicKey public_key;
+	PurpleConnection *gc = verify->client->application;
+	SilcPurple sg = gc->proto_data;
+
+	silc_pkcs_public_key_decode(verify->pk, verify->pk_len,
+				    &public_key);
+	silcpurple_show_public_key(sg, verify->entity_name, public_key,
+				 G_CALLBACK(silcpurple_verify_details_cb),
+				 verify);
+	silc_pkcs_public_key_free(public_key);
+}
+
+static void silcpurple_verify_ask(const char *entity,
+				const char *fingerprint,
+				const char *babbleprint,
+				PublicKeyVerify verify)
+{
+	PurpleConnection *gc = verify->client->application;
+	char tmp[256], tmp2[256];
+
+	if (verify->changed) {
+		g_snprintf(tmp, sizeof(tmp),
+			   _("Received %s's public key. Your local copy does not match this "
+			     "key. Would you still like to accept this public key?"),
+			   entity);
+	} else {
+		g_snprintf(tmp, sizeof(tmp),
+			   _("Received %s's public key. Would you like to accept this "
+			     "public key?"), entity);
+	}
+	g_snprintf(tmp2, sizeof(tmp2),
+		   _("Fingerprint and babbleprint for the %s key are:\n\n"
+		     "%s\n%s\n"), entity, fingerprint, babbleprint);
+
+	purple_request_action(gc, _("Verify Public Key"), tmp, tmp2,
+						PURPLE_DEFAULT_ACTION_NONE,
+						purple_connection_get_account(gc), entity, NULL, verify, 3,
+			    _("Yes"), G_CALLBACK(silcpurple_verify_cb),
+			    _("No"), G_CALLBACK(silcpurple_verify_cb),
+			    _("_View..."), G_CALLBACK(silcpurple_verify_details));
+}
+
+void silcpurple_verify_public_key(SilcClient client, SilcClientConnection conn,
+				const char *name, SilcSocketType conn_type,
+				unsigned char *pk, SilcUInt32 pk_len,
+				SilcSKEPKType pk_type,
+				SilcVerifyPublicKey completion, void *context)
+{
+	PurpleConnection *gc = client->application;
+	int i;
+	char file[256], filename[256], filename2[256], *ipf, *hostf = NULL;
+	char *fingerprint, *babbleprint;
+	struct passwd *pw;
+	struct stat st;
+	char *entity = ((conn_type == SILC_SOCKET_TYPE_SERVER ||
+			 conn_type == SILC_SOCKET_TYPE_ROUTER) ?
+			"server" : "client");
+	PublicKeyVerify verify;
+
+	if (pk_type != SILC_SKE_PK_TYPE_SILC) {
+		purple_notify_error(gc, _("Verify Public Key"),
+				  _("Unsupported public key type"), NULL);
+		if (completion)
+			completion(FALSE, context);
+		return;
+	}
+
+	pw = getpwuid(getuid());
+	if (!pw) {
+		if (completion)
+			completion(FALSE, context);
+		return;
+	}
+
+	memset(filename, 0, sizeof(filename));
+	memset(filename2, 0, sizeof(filename2));
+	memset(file, 0, sizeof(file));
+
+	if (conn_type == SILC_SOCKET_TYPE_SERVER ||
+	    conn_type == SILC_SOCKET_TYPE_ROUTER) {
+		if (!name) {
+			g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
+				   conn->sock->ip, conn->sock->port);
+			g_snprintf(filename, sizeof(filename) - 1,
+				   "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s",
+				   silcpurple_silcdir(), entity, file);
+
+			g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
+				   conn->sock->hostname, conn->sock->port);
+			g_snprintf(filename2, sizeof(filename2) - 1,
+				   "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s",
+				   silcpurple_silcdir(), entity, file);
+
+			ipf = filename;
+			hostf = filename2;
+		} else {
+			g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
+				   name, conn->sock->port);
+			g_snprintf(filename, sizeof(filename) - 1,
+				   "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s",
+				   silcpurple_silcdir(), entity, file);
+
+			ipf = filename;
+		}
+	} else {
+		/* Replace all whitespaces with `_'. */
+		fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
+		for (i = 0; i < strlen(fingerprint); i++)
+			if (fingerprint[i] == ' ')
+				fingerprint[i] = '_';
+
+		g_snprintf(file, sizeof(file) - 1, "%skey_%s.pub", entity, fingerprint);
+		g_snprintf(filename, sizeof(filename) - 1,
+			   "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s",
+			   silcpurple_silcdir(), entity, file);
+		silc_free(fingerprint);
+
+		ipf = filename;
+	}
+
+	verify = silc_calloc(1, sizeof(*verify));
+	if (!verify)
+		return;
+	verify->client = client;
+	verify->conn = conn;
+	verify->filename = strdup(ipf);
+	verify->entity = strdup(entity);
+	verify->entity_name = (conn_type != SILC_SOCKET_TYPE_CLIENT ?
+			       (name ? strdup(name) : strdup(conn->sock->hostname))
+			       : NULL);
+	verify->pk = silc_memdup(pk, pk_len);
+	verify->pk_len = pk_len;
+	verify->pk_type = pk_type;
+	verify->completion = completion;
+	verify->context = context;
+	fingerprint = verify->fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
+	babbleprint = verify->babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
+
+	/* Check whether this key already exists */
+	if (g_stat(ipf, &st) < 0 && (!hostf || g_stat(hostf, &st) < 0)) {
+		/* Key does not exist, ask user to verify the key and save it */
+		silcpurple_verify_ask(name ? name : entity,
+				    fingerprint, babbleprint, verify);
+		return;
+	} else {
+		/* The key already exists, verify it. */
+		SilcPublicKey public_key;
+		unsigned char *encpk;
+		SilcUInt32 encpk_len;
+
+		/* Load the key file, try for both IP filename and hostname filename */
+		if (!silc_pkcs_load_public_key(ipf, &public_key,
+					       SILC_PKCS_FILE_PEM) &&
+		    !silc_pkcs_load_public_key(ipf, &public_key,
+					       SILC_PKCS_FILE_BIN) &&
+		    (!hostf || (!silc_pkcs_load_public_key(hostf, &public_key,
+							   SILC_PKCS_FILE_PEM) &&
+				!silc_pkcs_load_public_key(hostf, &public_key,
+							   SILC_PKCS_FILE_BIN)))) {
+			silcpurple_verify_ask(name ? name : entity,
+					    fingerprint, babbleprint, verify);
+			return;
+		}
+
+		/* Encode the key data */
+		encpk = silc_pkcs_public_key_encode(public_key, &encpk_len);
+		if (!encpk) {
+			silcpurple_verify_ask(name ? name : entity,
+					    fingerprint, babbleprint, verify);
+			return;
+		}
+
+		/* Compare the keys */
+		if (memcmp(encpk, pk, encpk_len)) {
+			/* Ask user to verify the key and save it */
+			verify->changed = TRUE;
+			silcpurple_verify_ask(name ? name : entity,
+					    fingerprint, babbleprint, verify);
+			return;
+		}
+
+		/* Local copy matched */
+		if (completion)
+			completion(TRUE, context);
+		silc_free(verify->filename);
+		silc_free(verify->entity);
+		silc_free(verify->entity_name);
+		silc_free(verify->pk);
+		silc_free(verify->fingerprint);
+		silc_free(verify->babbleprint);
+		silc_free(verify);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/silc10/silc.c	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,1914 @@
+/*
+
+  silcpurple.c
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2004 - 2005 Pekka Riikonen
+
+  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; version 2 of the License.
+
+  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.
+
+*/
+
+#include "silcincludes.h"
+#include "silcclient.h"
+#include "silcpurple.h"
+#include "version.h"
+#include "wb.h"
+
+extern SilcClientOperations ops;
+static PurplePlugin *silc_plugin = NULL;
+
+static const char *
+silcpurple_list_icon(PurpleAccount *a, PurpleBuddy *b)
+{
+	return (const char *)"silc";
+}
+
+static GList *
+silcpurple_away_states(PurpleAccount *account)
+{
+	PurpleStatusType *type;
+	GList *types = NULL;
+
+	type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_AVAILABLE, NULL, FALSE, TRUE, FALSE);
+	types = g_list_append(types, type);
+	type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_HYPER, _("Hyper Active"), FALSE, TRUE, FALSE);
+	types = g_list_append(types, type);
+	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_AWAY, NULL, FALSE, TRUE, FALSE);
+	types = g_list_append(types, type);
+	type = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, SILCPURPLE_STATUS_ID_BUSY, _("Busy"), FALSE, TRUE, FALSE);
+	types = g_list_append(types, type);
+	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_INDISPOSED, _("Indisposed"), FALSE, TRUE, FALSE);
+	types = g_list_append(types, type);
+	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_PAGE, _("Wake Me Up"), FALSE, TRUE, FALSE);
+	types = g_list_append(types, type);
+	type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, SILCPURPLE_STATUS_ID_OFFLINE, NULL, FALSE, TRUE, FALSE);
+	types = g_list_append(types, type);
+
+	return types;
+}
+
+static void
+silcpurple_set_status(PurpleAccount *account, PurpleStatus *status)
+{
+	PurpleConnection *gc = purple_account_get_connection(account);
+	SilcPurple sg = NULL;
+	SilcUInt32 mode;
+	SilcBuffer idp;
+	unsigned char mb[4];
+	const char *state;
+
+	if (gc != NULL)
+		sg = gc->proto_data;
+
+	if (status == NULL)
+		return;
+
+	state = purple_status_get_id(status);
+
+	if (state == NULL)
+		return;
+
+	if ((sg == NULL) || (sg->conn == NULL))
+		return;
+
+	mode = sg->conn->local_entry->mode;
+	mode &= ~(SILC_UMODE_GONE |
+		  SILC_UMODE_HYPER |
+		  SILC_UMODE_BUSY |
+		  SILC_UMODE_INDISPOSED |
+		  SILC_UMODE_PAGE);
+
+	if (!strcmp(state, "hyper"))
+		mode |= SILC_UMODE_HYPER;
+	else if (!strcmp(state, "away"))
+		mode |= SILC_UMODE_GONE;
+	else if (!strcmp(state, "busy"))
+		mode |= SILC_UMODE_BUSY;
+	else if (!strcmp(state, "indisposed"))
+		mode |= SILC_UMODE_INDISPOSED;
+	else if (!strcmp(state, "page"))
+		mode |= SILC_UMODE_PAGE;
+
+	/* Send UMODE */
+	idp = silc_id_payload_encode(sg->conn->local_id, SILC_ID_CLIENT);
+	SILC_PUT32_MSB(mode, mb);
+	silc_client_command_send(sg->client, sg->conn, SILC_COMMAND_UMODE,
+				 ++sg->conn->cmd_ident, 2,
+				 1, idp->data, idp->len,
+				 2, mb, sizeof(mb));
+	silc_buffer_free(idp);
+}
+
+
+/*************************** Connection Routines *****************************/
+
+static void
+silcpurple_keepalive(PurpleConnection *gc)
+{
+	SilcPurple sg = gc->proto_data;
+	silc_client_send_packet(sg->client, sg->conn, SILC_PACKET_HEARTBEAT,
+				NULL, 0);
+}
+
+static gboolean
+silcpurple_scheduler(gpointer *context)
+{
+	SilcPurple sg = (SilcPurple)context;
+	silc_client_run_one(sg->client);
+	return TRUE;
+}
+
+static void
+silcpurple_nickname_parse(const char *nickname,
+			char **ret_nickname)
+{
+	silc_parse_userfqdn(nickname, ret_nickname, NULL);
+}
+
+static void
+silcpurple_login_connected(gpointer data, gint source, const gchar *error_message)
+{
+	PurpleConnection *gc = data;
+	SilcPurple sg;
+	SilcClient client;
+	SilcClientConnection conn;
+	PurpleAccount *account;
+	SilcClientConnectionParams params;
+	SilcUInt32 mask;
+	const char *dfile, *tmp;
+#ifdef SILC_ATTRIBUTE_USER_ICON
+	PurpleStoredImage *img;
+#endif
+#ifdef HAVE_SYS_UTSNAME_H
+	struct utsname u;
+#endif
+
+
+	g_return_if_fail(gc != NULL);
+
+	sg = gc->proto_data;
+
+	if (source < 0) {
+		purple_connection_error(gc, _("Connection failed"));
+		return;
+	}
+
+	client = sg->client;
+	account = sg->account;
+
+	/* Get session detachment data, if available */
+	memset(&params, 0, sizeof(params));
+	dfile = silcpurple_session_file(purple_account_get_username(sg->account));
+	params.detach_data = (unsigned char *)silc_file_readfile(dfile, &params.detach_data_len);
+	if (params.detach_data)
+		params.detach_data[params.detach_data_len] = 0;
+
+	/* Add connection to SILC client library */
+	conn = silc_client_add_connection(
+			  sg->client, &params,
+			  (char *)purple_account_get_string(account, "server",
+							  "silc.silcnet.org"),
+			  purple_account_get_int(account, "port", 706), sg);
+	if (!conn) {
+		purple_connection_error(gc, _("Cannot initialize SILC Client connection"));
+		gc->proto_data = NULL;
+		return;
+	}
+	sg->conn = conn;
+
+	/* Progress */
+	if (params.detach_data) {
+		purple_connection_update_progress(gc, _("Resuming session"), 2, 5);
+		sg->resuming = TRUE;
+	} else {
+		purple_connection_update_progress(gc, _("Performing key exchange"), 2, 5);
+	}
+
+	/* Perform SILC Key Exchange.  The "silc_connected" will be called
+	   eventually. */
+	silc_client_start_key_exchange(sg->client, sg->conn, source);
+
+	/* Set default attributes */
+	mask = SILC_ATTRIBUTE_MOOD_NORMAL;
+	silc_client_attribute_add(client, conn,
+				  SILC_ATTRIBUTE_STATUS_MOOD,
+				  SILC_32_TO_PTR(mask),
+				  sizeof(SilcUInt32));
+	mask = SILC_ATTRIBUTE_CONTACT_CHAT;
+	silc_client_attribute_add(client, conn,
+				  SILC_ATTRIBUTE_PREFERRED_CONTACT,
+				  SILC_32_TO_PTR(mask),
+				  sizeof(SilcUInt32));
+#ifdef HAVE_SYS_UTSNAME_H
+	if (!uname(&u)) {
+		SilcAttributeObjDevice dev;
+		memset(&dev, 0, sizeof(dev));
+		dev.type = SILC_ATTRIBUTE_DEVICE_COMPUTER;
+		dev.version = u.release;
+		dev.model = u.sysname;
+		silc_client_attribute_add(client, conn,
+					  SILC_ATTRIBUTE_DEVICE_INFO,
+					  (void *)&dev, sizeof(dev));
+	}
+#endif
+#ifdef _WIN32
+	tmp = _tzname[0];
+#else
+	tmp = tzname[0];
+#endif
+	silc_client_attribute_add(client, conn,
+				  SILC_ATTRIBUTE_TIMEZONE,
+				  (void *)tmp, strlen(tmp));
+
+#ifdef SILC_ATTRIBUTE_USER_ICON
+	/* Set our buddy icon */
+	img = purple_buddy_icons_find_account_icon(account);
+	silcpurple_buddy_set_icon(gc, img);
+	purple_imgstore_unref(img);
+#endif
+
+	silc_free(params.detach_data);
+}
+
+static void
+silcpurple_login(PurpleAccount *account)
+{
+	SilcPurple sg;
+	SilcClient client;
+	SilcClientParams params;
+	PurpleConnection *gc;
+	char pkd[256], prd[256];
+	const char *cipher, *hmac;
+	char *realname;
+	int i;
+
+	gc = account->gc;
+	if (!gc)
+		return;
+	gc->proto_data = NULL;
+
+	memset(&params, 0, sizeof(params));
+	strcat(params.nickname_format, "%n@%h%a");
+	params.nickname_parse = silcpurple_nickname_parse;
+	params.ignore_requested_attributes = FALSE;
+
+	/* Allocate SILC client */
+	client = silc_client_alloc(&ops, &params, gc, NULL);
+	if (!client) {
+		purple_connection_error(gc, _("Out of memory"));
+		return;
+	}
+
+	/* Get username, real name and local hostname for SILC library */
+	if (purple_account_get_username(account)) {
+		const char *u = purple_account_get_username(account);
+		char **up = g_strsplit(u, "@", 2);
+		client->username = strdup(up[0]);
+		g_strfreev(up);
+	} else {
+		client->username = silc_get_username();
+		purple_account_set_username(account, client->username);
+	}
+	realname = silc_get_real_name();
+	if (purple_account_get_user_info(account)) {
+		client->realname = strdup(purple_account_get_user_info(account));
+		free(realname);
+	} else if ((silc_get_real_name() != NULL) && (*realname != '\0')) {
+		client->realname = realname;
+		purple_account_set_user_info(account, client->realname);
+	} else {
+		free(realname);
+		client->realname = strdup(_("John Noname"));
+	}
+	client->hostname = silc_net_localhost();
+
+	purple_connection_set_display_name(gc, client->username);
+
+	/* Register requested cipher and HMAC */
+	cipher = purple_account_get_string(account, "cipher", SILC_DEFAULT_CIPHER);
+	for (i = 0; silc_default_ciphers[i].name; i++)
+		if (!strcmp(silc_default_ciphers[i].name, cipher)) {
+			silc_cipher_register(&(silc_default_ciphers[i]));
+			break;
+		}
+	hmac = purple_account_get_string(account, "hmac", SILC_DEFAULT_HMAC);
+	for (i = 0; silc_default_hmacs[i].name; i++)
+		if (!strcmp(silc_default_hmacs[i].name, hmac)) {
+			silc_hmac_register(&(silc_default_hmacs[i]));
+			break;
+		}
+
+	/* Init SILC client */
+	if (!silc_client_init(client)) {
+		gc->wants_to_die = TRUE;
+		purple_connection_error(gc, _("Cannot initialize SILC protocol"));
+		return;
+	}
+
+	/* Check the ~/.silc dir and create it, and new key pair if necessary. */
+	if (!silcpurple_check_silc_dir(gc)) {
+		gc->wants_to_die = TRUE;
+		purple_connection_error(gc, _("Cannot find/access ~/.silc directory"));
+		return;
+	}
+
+	/* Progress */
+	purple_connection_update_progress(gc, _("Connecting to SILC Server"), 1, 5);
+
+	/* Load SILC key pair */
+	g_snprintf(pkd, sizeof(pkd), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir());
+	g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir());
+	if (!silc_load_key_pair((char *)purple_account_get_string(account, "public-key", pkd),
+							(char *)purple_account_get_string(account, "private-key", prd),
+				(gc->password == NULL) ? "" : gc->password, &client->pkcs,
+				&client->public_key, &client->private_key)) {
+		g_snprintf(pkd, sizeof(pkd), _("Could not load SILC key pair: %s"), strerror(errno));
+		purple_connection_error(gc, pkd);
+		return;
+	}
+
+	sg = silc_calloc(1, sizeof(*sg));
+	if (!sg)
+		return;
+	memset(sg, 0, sizeof(*sg));
+	sg->client = client;
+	sg->gc = gc;
+	sg->account = account;
+	gc->proto_data = sg;
+
+	/* Connect to the SILC server */
+	if (purple_proxy_connect(gc, account,
+			       purple_account_get_string(account, "server",
+						       "silc.silcnet.org"),
+			       purple_account_get_int(account, "port", 706),
+			       silcpurple_login_connected, gc) == NULL)
+	{
+		purple_connection_error(gc, _("Unable to create connection"));
+		return;
+	}
+
+	/* Schedule SILC using Glib's event loop */
+	sg->scheduler = purple_timeout_add(300, (GSourceFunc)silcpurple_scheduler, sg);
+}
+
+static int
+silcpurple_close_final(gpointer *context)
+{
+	SilcPurple sg = (SilcPurple)context;
+	silc_client_stop(sg->client);
+	silc_client_free(sg->client);
+#ifdef HAVE_SILCMIME_H
+	if (sg->mimeass)
+		silc_mime_assembler_free(sg->mimeass);
+#endif
+	silc_free(sg);
+	return 0;
+}
+
+static void
+silcpurple_close(PurpleConnection *gc)
+{
+	SilcPurple sg = gc->proto_data;
+
+	g_return_if_fail(sg != NULL);
+
+	/* Send QUIT */
+	silc_client_command_call(sg->client, sg->conn, NULL,
+				 "QUIT", "Download this: " PURPLE_WEBSITE, NULL);
+
+	if (sg->conn)
+		silc_client_close_connection(sg->client, sg->conn);
+
+	purple_timeout_remove(sg->scheduler);
+	purple_timeout_add(1, (GSourceFunc)silcpurple_close_final, sg);
+}
+
+
+/****************************** Protocol Actions *****************************/
+
+static void
+silcpurple_attrs_cancel(PurpleConnection *gc, PurpleRequestFields *fields)
+{
+	/* Nothing */
+}
+
+static void
+silcpurple_attrs_cb(PurpleConnection *gc, PurpleRequestFields *fields)
+{
+	SilcPurple sg = gc->proto_data;
+	SilcClient client = sg->client;
+	SilcClientConnection conn = sg->conn;
+	PurpleRequestField *f;
+	char *tmp;
+	SilcUInt32 tmp_len, mask;
+	SilcAttributeObjService service;
+	SilcAttributeObjDevice dev;
+	SilcVCardStruct vcard;
+	const char *val;
+
+	sg = gc->proto_data;
+	if (!sg)
+		return;
+
+	memset(&service, 0, sizeof(service));
+	memset(&dev, 0, sizeof(dev));
+	memset(&vcard, 0, sizeof(vcard));
+
+	silc_client_attribute_del(client, conn,
+				  SILC_ATTRIBUTE_USER_INFO, NULL);
+	silc_client_attribute_del(client, conn,
+				  SILC_ATTRIBUTE_SERVICE, NULL);
+	silc_client_attribute_del(client, conn,
+				  SILC_ATTRIBUTE_STATUS_MOOD, NULL);
+	silc_client_attribute_del(client, conn,
+				  SILC_ATTRIBUTE_STATUS_FREETEXT, NULL);
+	silc_client_attribute_del(client, conn,
+				  SILC_ATTRIBUTE_STATUS_MESSAGE, NULL);
+	silc_client_attribute_del(client, conn,
+				  SILC_ATTRIBUTE_PREFERRED_LANGUAGE, NULL);
+	silc_client_attribute_del(client, conn,
+				  SILC_ATTRIBUTE_PREFERRED_CONTACT, NULL);
+	silc_client_attribute_del(client, conn,
+				  SILC_ATTRIBUTE_TIMEZONE, NULL);
+	silc_client_attribute_del(client, conn,
+				  SILC_ATTRIBUTE_GEOLOCATION, NULL);
+	silc_client_attribute_del(client, conn,
+				  SILC_ATTRIBUTE_DEVICE_INFO, NULL);
+
+	/* Set mood */
+	mask = 0;
+	f = purple_request_fields_get_field(fields, "mood_normal");
+	if (f && purple_request_field_bool_get_value(f))
+		mask |= SILC_ATTRIBUTE_MOOD_NORMAL;
+	f = purple_request_fields_get_field(fields, "mood_happy");
+	if (f && purple_request_field_bool_get_value(f))
+		mask |= SILC_ATTRIBUTE_MOOD_HAPPY;
+	f = purple_request_fields_get_field(fields, "mood_sad");
+	if (f && purple_request_field_bool_get_value(f))
+		mask |= SILC_ATTRIBUTE_MOOD_SAD;
+	f = purple_request_fields_get_field(fields, "mood_angry");
+	if (f && purple_request_field_bool_get_value(f))
+		mask |= SILC_ATTRIBUTE_MOOD_ANGRY;
+	f = purple_request_fields_get_field(fields, "mood_jealous");
+	if (f && purple_request_field_bool_get_value(f))
+		mask |= SILC_ATTRIBUTE_MOOD_JEALOUS;
+	f = purple_request_fields_get_field(fields, "mood_ashamed");
+	if (f && purple_request_field_bool_get_value(f))
+		mask |= SILC_ATTRIBUTE_MOOD_ASHAMED;
+	f = purple_request_fields_get_field(fields, "mood_invincible");
+	if (f && purple_request_field_bool_get_value(f))
+		mask |= SILC_ATTRIBUTE_MOOD_INVINCIBLE;
+	f = purple_request_fields_get_field(fields, "mood_inlove");
+	if (f && purple_request_field_bool_get_value(f))
+		mask |= SILC_ATTRIBUTE_MOOD_INLOVE;
+	f = purple_request_fields_get_field(fields, "mood_sleepy");
+	if (f && purple_request_field_bool_get_value(f))
+		mask |= SILC_ATTRIBUTE_MOOD_SLEEPY;
+	f = purple_request_fields_get_field(fields, "mood_bored");
+	if (f && purple_request_field_bool_get_value(f))
+		mask |= SILC_ATTRIBUTE_MOOD_BORED;
+	f = purple_request_fields_get_field(fields, "mood_excited");
+	if (f && purple_request_field_bool_get_value(f))
+		mask |= SILC_ATTRIBUTE_MOOD_EXCITED;
+	f = purple_request_fields_get_field(fields, "mood_anxious");
+	if (f && purple_request_field_bool_get_value(f))
+		mask |= SILC_ATTRIBUTE_MOOD_ANXIOUS;
+	silc_client_attribute_add(client, conn,
+				  SILC_ATTRIBUTE_STATUS_MOOD,
+				  SILC_32_TO_PTR(mask),
+				  sizeof(SilcUInt32));
+
+	/* Set preferred contact */
+	mask = 0;
+	f = purple_request_fields_get_field(fields, "contact_chat");
+	if (f && purple_request_field_bool_get_value(f))
+		mask |= SILC_ATTRIBUTE_CONTACT_CHAT;
+	f = purple_request_fields_get_field(fields, "contact_email");
+	if (f && purple_request_field_bool_get_value(f))
+		mask |= SILC_ATTRIBUTE_CONTACT_EMAIL;
+	f = purple_request_fields_get_field(fields, "contact_call");
+	if (f && purple_request_field_bool_get_value(f))
+		mask |= SILC_ATTRIBUTE_CONTACT_CALL;
+	f = purple_request_fields_get_field(fields, "contact_sms");
+	if (f && purple_request_field_bool_get_value(f))
+		mask |= SILC_ATTRIBUTE_CONTACT_SMS;
+	f = purple_request_fields_get_field(fields, "contact_mms");
+	if (f && purple_request_field_bool_get_value(f))
+		mask |= SILC_ATTRIBUTE_CONTACT_MMS;
+	f = purple_request_fields_get_field(fields, "contact_video");
+	if (f && purple_request_field_bool_get_value(f))
+		mask |= SILC_ATTRIBUTE_CONTACT_VIDEO;
+	if (mask)
+		silc_client_attribute_add(client, conn,
+					  SILC_ATTRIBUTE_PREFERRED_CONTACT,
+					  SILC_32_TO_PTR(mask),
+					  sizeof(SilcUInt32));
+
+	/* Set status text */
+	val = NULL;
+	f = purple_request_fields_get_field(fields, "status_text");
+	if (f)
+		val = purple_request_field_string_get_value(f);
+	if (val && *val)
+		silc_client_attribute_add(client, conn,
+					  SILC_ATTRIBUTE_STATUS_FREETEXT,
+					  (void *)val, strlen(val));
+
+	/* Set vcard */
+	val = NULL;
+	f = purple_request_fields_get_field(fields, "vcard");
+	if (f)
+		val = purple_request_field_string_get_value(f);
+	if (val && *val) {
+		purple_account_set_string(sg->account, "vcard", val);
+		tmp = silc_file_readfile(val, &tmp_len);
+		if (tmp) {
+			tmp[tmp_len] = 0;
+			if (silc_vcard_decode((unsigned char *)tmp, tmp_len, &vcard))
+				silc_client_attribute_add(client, conn,
+							  SILC_ATTRIBUTE_USER_INFO,
+							  (void *)&vcard,
+							  sizeof(vcard));
+		}
+		silc_vcard_free(&vcard);
+		silc_free(tmp);
+	} else {
+		purple_account_set_string(sg->account, "vcard", "");
+	}
+
+#ifdef HAVE_SYS_UTSNAME_H
+	/* Set device info */
+	f = purple_request_fields_get_field(fields, "device");
+	if (f && purple_request_field_bool_get_value(f)) {
+		struct utsname u;
+		if (!uname(&u)) {
+			dev.type = SILC_ATTRIBUTE_DEVICE_COMPUTER;
+			dev.version = u.release;
+			dev.model = u.sysname;
+			silc_client_attribute_add(client, conn,
+						  SILC_ATTRIBUTE_DEVICE_INFO,
+						  (void *)&dev, sizeof(dev));
+		}
+	}
+#endif
+
+	/* Set timezone */
+	val = NULL;
+	f = purple_request_fields_get_field(fields, "timezone");
+	if (f)
+		val = purple_request_field_string_get_value(f);
+	if (val && *val)
+		silc_client_attribute_add(client, conn,
+					  SILC_ATTRIBUTE_TIMEZONE,
+					  (void *)val, strlen(val));
+}
+
+static void
+silcpurple_attrs(PurplePluginAction *action)
+{
+	PurpleConnection *gc = (PurpleConnection *) action->context;
+	SilcPurple sg = gc->proto_data;
+	SilcClient client = sg->client;
+	SilcClientConnection conn = sg->conn;
+	PurpleRequestFields *fields;
+	PurpleRequestFieldGroup *g;
+	PurpleRequestField *f;
+	SilcHashTable attrs;
+	SilcAttributePayload attr;
+	gboolean mnormal = TRUE, mhappy = FALSE, msad = FALSE,
+		mangry = FALSE, mjealous = FALSE, mashamed = FALSE,
+		minvincible = FALSE, minlove = FALSE, msleepy = FALSE,
+		mbored = FALSE, mexcited = FALSE, manxious = FALSE;
+	gboolean cemail = FALSE, ccall = FALSE, csms = FALSE,
+		cmms = FALSE, cchat = TRUE, cvideo = FALSE;
+	gboolean device = TRUE;
+	char status[1024];
+
+	sg = gc->proto_data;
+	if (!sg)
+		return;
+
+	memset(status, 0, sizeof(status));
+
+	attrs = silc_client_attributes_get(client, conn);
+	if (attrs) {
+		if (silc_hash_table_find(attrs,
+					 SILC_32_TO_PTR(SILC_ATTRIBUTE_STATUS_MOOD),
+					 NULL, (void *)&attr)) {
+			SilcUInt32 mood = 0;
+			silc_attribute_get_object(attr, &mood, sizeof(mood));
+			mnormal = !mood;
+			mhappy = (mood & SILC_ATTRIBUTE_MOOD_HAPPY);
+			msad = (mood & SILC_ATTRIBUTE_MOOD_SAD);
+			mangry = (mood & SILC_ATTRIBUTE_MOOD_ANGRY);
+			mjealous = (mood & SILC_ATTRIBUTE_MOOD_JEALOUS);
+			mashamed = (mood & SILC_ATTRIBUTE_MOOD_ASHAMED);
+			minvincible = (mood & SILC_ATTRIBUTE_MOOD_INVINCIBLE);
+			minlove = (mood & SILC_ATTRIBUTE_MOOD_INLOVE);
+			msleepy = (mood & SILC_ATTRIBUTE_MOOD_SLEEPY);
+			mbored = (mood & SILC_ATTRIBUTE_MOOD_BORED);
+			mexcited = (mood & SILC_ATTRIBUTE_MOOD_EXCITED);
+			manxious = (mood & SILC_ATTRIBUTE_MOOD_ANXIOUS);
+		}
+
+		if (silc_hash_table_find(attrs,
+					 SILC_32_TO_PTR(SILC_ATTRIBUTE_PREFERRED_CONTACT),
+					 NULL, (void *)&attr)) {
+			SilcUInt32 contact = 0;
+			silc_attribute_get_object(attr, &contact, sizeof(contact));
+			cemail = (contact & SILC_ATTRIBUTE_CONTACT_EMAIL);
+			ccall = (contact & SILC_ATTRIBUTE_CONTACT_CALL);
+			csms = (contact & SILC_ATTRIBUTE_CONTACT_SMS);
+			cmms = (contact & SILC_ATTRIBUTE_CONTACT_MMS);
+			cchat = (contact & SILC_ATTRIBUTE_CONTACT_CHAT);
+			cvideo = (contact & SILC_ATTRIBUTE_CONTACT_VIDEO);
+		}
+
+		if (silc_hash_table_find(attrs,
+					 SILC_32_TO_PTR(SILC_ATTRIBUTE_STATUS_FREETEXT),
+					 NULL, (void *)&attr))
+			silc_attribute_get_object(attr, &status, sizeof(status));
+
+		if (!silc_hash_table_find(attrs,
+					  SILC_32_TO_PTR(SILC_ATTRIBUTE_DEVICE_INFO),
+					  NULL, (void *)&attr))
+			device = FALSE;
+	}
+
+	fields = purple_request_fields_new();
+
+	g = purple_request_field_group_new(NULL);
+	f = purple_request_field_label_new("l3", _("Your Current Mood"));
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_bool_new("mood_normal", _("Normal"), mnormal);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_bool_new("mood_happy", _("Happy"), mhappy);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_bool_new("mood_sad", _("Sad"), msad);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_bool_new("mood_angry", _("Angry"), mangry);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_bool_new("mood_jealous", _("Jealous"), mjealous);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_bool_new("mood_ashamed", _("Ashamed"), mashamed);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_bool_new("mood_invincible", _("Invincible"), minvincible);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_bool_new("mood_inlove", _("In love"), minlove);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_bool_new("mood_sleepy", _("Sleepy"), msleepy);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_bool_new("mood_bored", _("Bored"), mbored);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_bool_new("mood_excited", _("Excited"), mexcited);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_bool_new("mood_anxious", _("Anxious"), manxious);
+	purple_request_field_group_add_field(g, f);
+
+	f = purple_request_field_label_new("l4", _("\nYour Preferred Contact Methods"));
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_bool_new("contact_chat", _("Chat"), cchat);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_bool_new("contact_email", _("E-mail"), cemail);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_bool_new("contact_call", _("Phone"), ccall);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_bool_new("contact_sms", _("SMS"), csms);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_bool_new("contact_mms", _("MMS"), cmms);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_bool_new("contact_video", _("Video conferencing"), cvideo);
+	purple_request_field_group_add_field(g, f);
+	purple_request_fields_add_group(fields, g);
+
+	g = purple_request_field_group_new(NULL);
+	f = purple_request_field_string_new("status_text", _("Your Current Status"),
+					  status[0] ? status : NULL, TRUE);
+	purple_request_field_group_add_field(g, f);
+	purple_request_fields_add_group(fields, g);
+
+	g = purple_request_field_group_new(NULL);
+#if 0
+	f = purple_request_field_label_new("l2", _("Online Services"));
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_bool_new("services",
+					_("Let others see what services you are using"),
+					TRUE);
+	purple_request_field_group_add_field(g, f);
+#endif
+#ifdef HAVE_SYS_UTSNAME_H
+	f = purple_request_field_bool_new("device",
+					_("Let others see what computer you are using"),
+					device);
+	purple_request_field_group_add_field(g, f);
+#endif
+	purple_request_fields_add_group(fields, g);
+
+	g = purple_request_field_group_new(NULL);
+	f = purple_request_field_string_new("vcard", _("Your VCard File"),
+					  purple_account_get_string(sg->account, "vcard", ""),
+					  FALSE);
+	purple_request_field_group_add_field(g, f);
+#ifdef _WIN32
+	f = purple_request_field_string_new("timezone", _("Timezone"), _tzname[0], FALSE);
+#else
+	f = purple_request_field_string_new("timezone", _("Timezone"), tzname[0], FALSE);
+#endif
+	purple_request_field_group_add_field(g, f);
+	purple_request_fields_add_group(fields, g);
+
+	purple_request_fields(gc, _("User Online Status Attributes"),
+			    _("User Online Status Attributes"),
+			    _("You can let other users see your online status information "
+			      "and your personal information. Please fill the information "
+			      "you would like other users to see about yourself."),
+			    fields,
+			    _("OK"), G_CALLBACK(silcpurple_attrs_cb),
+			    _("Cancel"), G_CALLBACK(silcpurple_attrs_cancel),
+				gc->account, NULL, NULL, gc);
+}
+
+static void
+silcpurple_detach(PurplePluginAction *action)
+{
+	PurpleConnection *gc = (PurpleConnection *) action->context;
+	SilcPurple sg;
+
+	if (!gc)
+		return;
+	sg = gc->proto_data;
+	if (!sg)
+		return;
+
+	/* Call DETACH */
+	silc_client_command_call(sg->client, sg->conn, "DETACH");
+	sg->detaching = TRUE;
+}
+
+static void
+silcpurple_view_motd(PurplePluginAction *action)
+{
+	PurpleConnection *gc = (PurpleConnection *) action->context;
+	SilcPurple sg;
+	char *tmp;
+
+	if (!gc)
+		return;
+	sg = gc->proto_data;
+	if (!sg)
+		return;
+
+	if (!sg->motd) {
+		purple_notify_error(
+		     gc, _("Message of the Day"), _("No Message of the Day available"),
+		     _("There is no Message of the Day associated with this connection"));
+		return;
+	}
+
+	tmp = g_markup_escape_text(sg->motd, -1);
+	purple_notify_formatted(gc, NULL, _("Message of the Day"), NULL,
+			      tmp, NULL, NULL);
+	g_free(tmp);
+}
+
+static void
+silcpurple_create_keypair_cancel(PurpleConnection *gc, PurpleRequestFields *fields)
+{
+	/* Nothing */
+}
+
+static void
+silcpurple_create_keypair_cb(PurpleConnection *gc, PurpleRequestFields *fields)
+{
+	SilcPurple sg = gc->proto_data;
+	PurpleRequestField *f;
+	const char *val, *pkfile = NULL, *prfile = NULL;
+	const char *pass1 = NULL, *pass2 = NULL, *un = NULL, *hn = NULL;
+	const char *rn = NULL, *e = NULL, *o = NULL, *c = NULL;
+	char *identifier;
+	int keylen = SILCPURPLE_DEF_PKCS_LEN;
+	SilcPublicKey public_key;
+
+	sg = gc->proto_data;
+	if (!sg)
+		return;
+
+	val = NULL;
+	f = purple_request_fields_get_field(fields, "pass1");
+	if (f)
+		val = purple_request_field_string_get_value(f);
+	if (val && *val)
+		pass1 = val;
+	else
+		pass1 = "";
+	val = NULL;
+	f = purple_request_fields_get_field(fields, "pass2");
+	if (f)
+		val = purple_request_field_string_get_value(f);
+	if (val && *val)
+		pass2 = val;
+	else
+		pass2 = "";
+
+	if (strcmp(pass1, pass2)) {
+		purple_notify_error(
+		     gc, _("Create New SILC Key Pair"), _("Passphrases do not match"), NULL);
+		return;
+	}
+
+	val = NULL;
+	f = purple_request_fields_get_field(fields, "key");
+	if (f)
+		val = purple_request_field_string_get_value(f);
+	if (val && *val)
+		keylen = atoi(val);
+	f = purple_request_fields_get_field(fields, "pkfile");
+	if (f)
+		pkfile = purple_request_field_string_get_value(f);
+	f = purple_request_fields_get_field(fields, "prfile");
+	if (f)
+		prfile = purple_request_field_string_get_value(f);
+
+	f = purple_request_fields_get_field(fields, "un");
+	if (f)
+		un = purple_request_field_string_get_value(f);
+	f = purple_request_fields_get_field(fields, "hn");
+	if (f)
+		hn = purple_request_field_string_get_value(f);
+	f = purple_request_fields_get_field(fields, "rn");
+	if (f)
+		rn = purple_request_field_string_get_value(f);
+	f = purple_request_fields_get_field(fields, "e");
+	if (f)
+		e = purple_request_field_string_get_value(f);
+	f = purple_request_fields_get_field(fields, "o");
+	if (f)
+		o = purple_request_field_string_get_value(f);
+	f = purple_request_fields_get_field(fields, "c");
+	if (f)
+		c = purple_request_field_string_get_value(f);
+
+	identifier = silc_pkcs_encode_identifier((char *)un, (char *)hn,
+						 (char *)rn, (char *)e, (char *)o, (char *)c);
+
+	/* Create the key pair */
+	if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS, keylen, pkfile, prfile,
+				  identifier, pass1, NULL, &public_key, NULL,
+				  FALSE)) {
+		purple_notify_error(
+		     gc, _("Create New SILC Key Pair"), _("Key Pair Generation failed"), NULL);
+		return;
+	}
+
+	silcpurple_show_public_key(sg, NULL, public_key, NULL, NULL);
+
+	silc_pkcs_public_key_free(public_key);
+	silc_free(identifier);
+}
+
+static void
+silcpurple_create_keypair(PurplePluginAction *action)
+{
+	PurpleConnection *gc = (PurpleConnection *) action->context;
+	SilcPurple sg = gc->proto_data;
+	PurpleRequestFields *fields;
+	PurpleRequestFieldGroup *g;
+	PurpleRequestField *f;
+	const char *username, *realname;
+	char *hostname, **u;
+	char tmp[256], pkd[256], pkd2[256], prd[256], prd2[256];
+
+	username = purple_account_get_username(sg->account);
+	u = g_strsplit(username, "@", 2);
+	username = u[0];
+	realname = purple_account_get_user_info(sg->account);
+	hostname = silc_net_localhost();
+	g_snprintf(tmp, sizeof(tmp), "%s@%s", username, hostname);
+
+	g_snprintf(pkd2, sizeof(pkd2), "%s" G_DIR_SEPARATOR_S"public_key.pub", silcpurple_silcdir());
+	g_snprintf(prd2, sizeof(prd2), "%s" G_DIR_SEPARATOR_S"private_key.prv", silcpurple_silcdir());
+	g_snprintf(pkd, sizeof(pkd) - 1, "%s",
+		   purple_account_get_string(gc->account, "public-key", pkd2));
+	g_snprintf(prd, sizeof(prd) - 1, "%s",
+		   purple_account_get_string(gc->account, "private-key", prd2));
+
+	fields = purple_request_fields_new();
+
+	g = purple_request_field_group_new(NULL);
+	f = purple_request_field_string_new("key", _("Key length"), "2048", FALSE);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_string_new("pkfile", _("Public key file"), pkd, FALSE);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_string_new("prfile", _("Private key file"), prd, FALSE);
+	purple_request_field_group_add_field(g, f);
+	purple_request_fields_add_group(fields, g);
+
+	g = purple_request_field_group_new(NULL);
+	f = purple_request_field_string_new("un", _("Username"), username ? username : "", FALSE);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_string_new("hn", _("Hostname"), hostname ? hostname : "", FALSE);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_string_new("rn", _("Real name"), realname ? realname : "", FALSE);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_string_new("e", _("E-mail"), tmp, FALSE);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_string_new("o", _("Organization"), "", FALSE);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_string_new("c", _("Country"), "", FALSE);
+	purple_request_field_group_add_field(g, f);
+	purple_request_fields_add_group(fields, g);
+
+	g = purple_request_field_group_new(NULL);
+	f = purple_request_field_string_new("pass1", _("Passphrase"), "", FALSE);
+	purple_request_field_string_set_masked(f, TRUE);
+	purple_request_field_group_add_field(g, f);
+	f = purple_request_field_string_new("pass2", _("Passphrase (retype)"), "", FALSE);
+	purple_request_field_string_set_masked(f, TRUE);
+	purple_request_field_group_add_field(g, f);
+	purple_request_fields_add_group(fields, g);
+
+	purple_request_fields(gc, _("Create New SILC Key Pair"),
+			    _("Create New SILC Key Pair"), NULL, fields,
+			    _("Generate Key Pair"), G_CALLBACK(silcpurple_create_keypair_cb),
+			    _("Cancel"), G_CALLBACK(silcpurple_create_keypair_cancel),
+				gc->account, NULL, NULL, gc);
+
+	g_strfreev(u);
+	silc_free(hostname);
+}
+
+static void
+silcpurple_change_pass(PurplePluginAction *action)
+{
+	PurpleConnection *gc = (PurpleConnection *) action->context;
+	purple_account_request_change_password(purple_connection_get_account(gc));
+}
+
+static void
+silcpurple_change_passwd(PurpleConnection *gc, const char *old, const char *new)
+{
+        char prd[256];
+	g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.pub", silcpurple_silcdir());
+	silc_change_private_key_passphrase(purple_account_get_string(gc->account,
+								   "private-key",
+								   prd), old, new);
+}
+
+static void
+silcpurple_show_set_info(PurplePluginAction *action)
+{
+	PurpleConnection *gc = (PurpleConnection *) action->context;
+	purple_account_request_change_user_info(purple_connection_get_account(gc));
+}
+
+static void
+silcpurple_set_info(PurpleConnection *gc, const char *text)
+{
+}
+
+static GList *
+silcpurple_actions(PurplePlugin *plugin, gpointer context)
+{
+	GList *list = NULL;
+	PurplePluginAction *act;
+
+	act = purple_plugin_action_new(_("Online Status"),
+			silcpurple_attrs);
+	list = g_list_append(list, act);
+
+	act = purple_plugin_action_new(_("Detach From Server"),
+			silcpurple_detach);
+	list = g_list_append(list, act);
+
+	act = purple_plugin_action_new(_("View Message of the Day"),
+			silcpurple_view_motd);
+	list = g_list_append(list, act);
+
+	act = purple_plugin_action_new(_("Create SILC Key Pair..."),
+			silcpurple_create_keypair);
+	list = g_list_append(list, act);
+
+	act = purple_plugin_action_new(_("Change Password..."),
+			silcpurple_change_pass);
+	list = g_list_append(list, act);
+
+	act = purple_plugin_action_new(_("Set User Info..."),
+			silcpurple_show_set_info);
+	list = g_list_append(list, act);
+
+	return list;
+}
+
+
+/******************************* IM Routines *********************************/
+
+typedef struct {
+	char *nick;
+	char *message;
+	SilcUInt32 message_len;
+	SilcMessageFlags flags;
+	PurpleMessageFlags gflags;
+} *SilcPurpleIM;
+
+static void
+silcpurple_send_im_resolved(SilcClient client,
+			  SilcClientConnection conn,
+			  SilcClientEntry *clients,
+			  SilcUInt32 clients_count,
+			  void *context)
+{
+	PurpleConnection *gc = client->application;
+	SilcPurple sg = gc->proto_data;
+	SilcPurpleIM im = context;
+	PurpleConversation *convo;
+	char tmp[256], *nickname = NULL;
+	SilcClientEntry client_entry;
+#ifdef HAVE_SILCMIME_H
+	SilcDList list;
+#endif
+
+	convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, im->nick,
+							sg->account);
+	if (!convo)
+		return;
+
+	if (!clients)
+		goto err;
+
+	if (clients_count > 1) {
+		silc_parse_userfqdn(im->nick, &nickname, NULL);
+
+		/* Find the correct one. The im->nick might be a formatted nick
+		   so this will find the correct one. */
+		clients = silc_client_get_clients_local(client, conn,
+							nickname, im->nick,
+							&clients_count);
+		if (!clients)
+			goto err;
+		client_entry = clients[0];
+		silc_free(clients);
+	} else {
+		client_entry = clients[0];
+	}
+
+#ifdef HAVE_SILCMIME_H
+	/* Check for images */
+	if (im->gflags & PURPLE_MESSAGE_IMAGES) {
+		list = silcpurple_image_message(im->message, (SilcUInt32 *)&im->flags);
+		if (list) {
+			/* Send one or more MIME message.  If more than one, they
+			   are MIME fragments due to over large message */
+			SilcBuffer buf;
+
+			silc_dlist_start(list);
+			while ((buf = silc_dlist_get(list)) != SILC_LIST_END)
+				silc_client_send_private_message(client, conn,
+								 client_entry, im->flags,
+								 buf->data, buf->len,
+								 TRUE);
+			silc_mime_partial_free(list);
+			purple_conv_im_write(PURPLE_CONV_IM(convo), conn->local_entry->nickname,
+				   im->message, 0, time(NULL));
+			goto out;
+		}
+	}
+#endif
+
+	/* Send the message */
+	silc_client_send_private_message(client, conn, client_entry, im->flags,
+					 (unsigned char *)im->message, im->message_len, TRUE);
+	purple_conv_im_write(PURPLE_CONV_IM(convo), conn->local_entry->nickname,
+			   im->message, 0, time(NULL));
+	goto out;
+
+ err:
+	g_snprintf(tmp, sizeof(tmp),
+		   _("User <I>%s</I> is not present in the network"), im->nick);
+	purple_conversation_write(convo, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL));
+
+ out:
+	g_free(im->nick);
+	g_free(im->message);
+	silc_free(im);
+	silc_free(nickname);
+}
+
+static int
+silcpurple_send_im(PurpleConnection *gc, const char *who, const char *message,
+		 PurpleMessageFlags flags)
+{
+	SilcPurple sg = gc->proto_data;
+	SilcClient client = sg->client;
+	SilcClientConnection conn = sg->conn;
+	SilcClientEntry *clients;
+	SilcUInt32 clients_count, mflags;
+	char *nickname, *msg, *tmp;
+	int ret = 0;
+	gboolean sign = purple_account_get_bool(sg->account, "sign-verify", FALSE);
+#ifdef HAVE_SILCMIME_H
+	SilcDList list;
+#endif
+
+	if (!who || !message)
+		return 0;
+
+	mflags = SILC_MESSAGE_FLAG_UTF8;
+
+	tmp = msg = purple_unescape_html(message);
+
+	if (!g_ascii_strncasecmp(msg, "/me ", 4)) {
+		msg += 4;
+		if (!*msg) {
+			g_free(tmp);
+			return 0;
+		}
+		mflags |= SILC_MESSAGE_FLAG_ACTION;
+	} else if (strlen(msg) > 1 && msg[0] == '/') {
+		if (!silc_client_command_call(client, conn, msg + 1))
+			purple_notify_error(gc, _("Call Command"), _("Cannot call command"),
+					_("Unknown command"));
+		g_free(tmp);
+		return 0;
+	}
+
+
+	if (!silc_parse_userfqdn(who, &nickname, NULL)) {
+		g_free(tmp);
+		return 0;
+	}
+
+	if (sign)
+		mflags |= SILC_MESSAGE_FLAG_SIGNED;
+
+	/* Find client entry */
+	clients = silc_client_get_clients_local(client, conn, nickname, who,
+						&clients_count);
+	if (!clients) {
+		/* Resolve unknown user */
+		SilcPurpleIM im = silc_calloc(1, sizeof(*im));
+		if (!im) {
+			g_free(tmp);
+			return 0;
+		}
+		im->nick = g_strdup(who);
+		im->message = g_strdup(message);
+		im->message_len = strlen(im->message);
+		im->flags = mflags;
+		im->gflags = flags;
+		silc_client_get_clients(client, conn, nickname, NULL,
+					silcpurple_send_im_resolved, im);
+		silc_free(nickname);
+		g_free(tmp);
+		return 0;
+	}
+
+#ifdef HAVE_SILCMIME_H
+	/* Check for images */
+	if (flags & PURPLE_MESSAGE_IMAGES) {
+		list = silcpurple_image_message(message, &mflags);
+		if (list) {
+			/* Send one or more MIME message.  If more than one, they
+			   are MIME fragments due to over large message */
+			SilcBuffer buf;
+
+			silc_dlist_start(list);
+			while ((buf = silc_dlist_get(list)) != SILC_LIST_END)
+				ret =
+			 	silc_client_send_private_message(client, conn,
+								 clients[0], mflags,
+								 buf->data, buf->len,
+								 TRUE);
+			silc_mime_partial_free(list);
+			g_free(tmp);
+			silc_free(nickname);
+			silc_free(clients);
+			return ret;
+		}
+	}
+#endif
+
+	/* Send private message directly */
+	ret = silc_client_send_private_message(client, conn, clients[0],
+					       mflags,
+					       (unsigned char *)msg,
+					       strlen(msg), TRUE);
+
+	g_free(tmp);
+	silc_free(nickname);
+	silc_free(clients);
+	return ret;
+}
+
+
+static GList *silcpurple_blist_node_menu(PurpleBlistNode *node) {
+	/* split this single menu building function back into the two
+	   original: one for buddies and one for chats */
+
+	if(PURPLE_BLIST_NODE_IS_CHAT(node)) {
+		return silcpurple_chat_menu((PurpleChat *) node);
+	} else if(PURPLE_BLIST_NODE_IS_BUDDY(node)) {
+		return silcpurple_buddy_menu((PurpleBuddy *) node);
+	} else {
+		g_return_val_if_reached(NULL);
+	}
+}
+
+/********************************* Commands **********************************/
+
+static PurpleCmdRet silcpurple_cmd_chat_part(PurpleConversation *conv,
+		const char *cmd, char **args, char **error, void *data)
+{
+	PurpleConnection *gc;
+	PurpleConversation *convo = conv;
+	int id = 0;
+
+	gc = purple_conversation_get_gc(conv);
+
+	if (gc == NULL)
+		return PURPLE_CMD_RET_FAILED;
+
+	if(args && args[0])
+		convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, args[0],
+									gc->account);
+
+	if (convo != NULL)
+		id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo));
+
+	if (id == 0)
+		return PURPLE_CMD_RET_FAILED;
+
+	silcpurple_chat_leave(gc, id);
+
+	return PURPLE_CMD_RET_OK;
+
+}
+
+static PurpleCmdRet silcpurple_cmd_chat_topic(PurpleConversation *conv,
+		const char *cmd, char **args, char **error, void *data)
+{
+	PurpleConnection *gc;
+	int id = 0;
+	char *buf, *tmp, *tmp2;
+	const char *topic;
+
+	gc = purple_conversation_get_gc(conv);
+	id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv));
+
+	if (gc == NULL || id == 0)
+		return PURPLE_CMD_RET_FAILED;
+
+	if (!args || !args[0]) {
+		topic = purple_conv_chat_get_topic (PURPLE_CONV_CHAT(conv));
+		if (topic) {
+			tmp = g_markup_escape_text(topic, -1);
+			tmp2 = purple_markup_linkify(tmp);
+			buf = g_strdup_printf(_("current topic is: %s"), tmp2);
+			g_free(tmp);
+			g_free(tmp2);
+		} else
+			buf = g_strdup(_("No topic is set"));
+		purple_conv_chat_write(PURPLE_CONV_CHAT(conv), gc->account->username, buf,
+							 PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL));
+		g_free(buf);
+
+	}
+
+	if (args && args[0] && (strlen(args[0]) > 255)) {
+		*error = g_strdup(_("Topic too long"));
+		return PURPLE_CMD_RET_FAILED;
+	}
+
+	silcpurple_chat_set_topic(gc, id, args ? args[0] : NULL);
+
+	return PURPLE_CMD_RET_OK;
+}
+
+static PurpleCmdRet silcpurple_cmd_chat_join(PurpleConversation *conv,
+        const char *cmd, char **args, char **error, void *data)
+{
+	GHashTable *comp;
+
+	if(!args || !args[0])
+		return PURPLE_CMD_RET_FAILED;
+
+	comp = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
+
+	g_hash_table_replace(comp, "channel", args[0]);
+	if(args[1])
+		g_hash_table_replace(comp, "passphrase", args[1]);
+
+	silcpurple_chat_join(purple_conversation_get_gc(conv), comp);
+
+	g_hash_table_destroy(comp);
+	return PURPLE_CMD_RET_OK;
+}
+
+static PurpleCmdRet silcpurple_cmd_chat_list(PurpleConversation *conv,
+        const char *cmd, char **args, char **error, void *data)
+{
+	PurpleConnection *gc;
+	gc = purple_conversation_get_gc(conv);
+	purple_roomlist_show_with_account(purple_connection_get_account(gc));
+	return PURPLE_CMD_RET_OK;
+}
+
+static PurpleCmdRet silcpurple_cmd_whois(PurpleConversation *conv,
+		const char *cmd, char **args, char **error, void *data)
+{
+	PurpleConnection *gc;
+
+	gc = purple_conversation_get_gc(conv);
+
+	if (gc == NULL)
+		return PURPLE_CMD_RET_FAILED;
+
+	silcpurple_get_info(gc, args[0]);
+
+	return PURPLE_CMD_RET_OK;
+}
+
+static PurpleCmdRet silcpurple_cmd_msg(PurpleConversation *conv,
+		const char *cmd, char **args, char **error, void *data)
+{
+	int ret;
+	PurpleConnection *gc;
+
+	gc = purple_conversation_get_gc(conv);
+
+	if (gc == NULL)
+		return PURPLE_CMD_RET_FAILED;
+
+	ret = silcpurple_send_im(gc, args[0], args[1], PURPLE_MESSAGE_SEND);
+
+	if (ret)
+		return PURPLE_CMD_RET_OK;
+	else
+		return PURPLE_CMD_RET_FAILED;
+}
+
+static PurpleCmdRet silcpurple_cmd_query(PurpleConversation *conv,
+		const char *cmd, char **args, char **error, void *data)
+{
+	int ret = 1;
+	PurpleConversation *convo;
+	PurpleConnection *gc;
+	PurpleAccount *account;
+
+	if (!args || !args[0]) {
+		*error = g_strdup(_("You must specify a nick"));
+		return PURPLE_CMD_RET_FAILED;
+	}
+
+	gc = purple_conversation_get_gc(conv);
+
+	if (gc == NULL)
+		return PURPLE_CMD_RET_FAILED;
+
+	account = purple_connection_get_account(gc);
+
+	convo = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, args[0]);
+
+	if (args[1]) {
+		ret = silcpurple_send_im(gc, args[0], args[1], PURPLE_MESSAGE_SEND);
+		purple_conv_im_write(PURPLE_CONV_IM(convo), purple_connection_get_display_name(gc),
+				args[1], PURPLE_MESSAGE_SEND, time(NULL));
+	}
+
+	if (ret)
+		return PURPLE_CMD_RET_OK;
+	else
+		return PURPLE_CMD_RET_FAILED;
+}
+
+static PurpleCmdRet silcpurple_cmd_motd(PurpleConversation *conv,
+		const char *cmd, char **args, char **error, void *data)
+{
+	PurpleConnection *gc;
+	SilcPurple sg;
+	char *tmp;
+
+	gc = purple_conversation_get_gc(conv);
+
+	if (gc == NULL)
+		return PURPLE_CMD_RET_FAILED;
+
+	sg = gc->proto_data;
+
+	if (sg == NULL)
+		return PURPLE_CMD_RET_FAILED;
+
+	if (!sg->motd) {
+		*error = g_strdup(_("There is no Message of the Day associated with this connection"));
+		return PURPLE_CMD_RET_FAILED;
+	}
+
+	tmp = g_markup_escape_text(sg->motd, -1);
+	purple_notify_formatted(gc, NULL, _("Message of the Day"), NULL,
+			tmp, NULL, NULL);
+	g_free(tmp);
+
+	return PURPLE_CMD_RET_OK;
+}
+
+static PurpleCmdRet silcpurple_cmd_detach(PurpleConversation *conv,
+		const char *cmd, char **args, char **error, void *data)
+{
+	PurpleConnection *gc;
+	SilcPurple sg;
+
+	gc = purple_conversation_get_gc(conv);
+
+	if (gc == NULL)
+		return PURPLE_CMD_RET_FAILED;
+
+	sg = gc->proto_data;
+
+	if (sg == NULL)
+		return PURPLE_CMD_RET_FAILED;
+
+	silc_client_command_call(sg->client, sg->conn, "DETACH");
+	sg->detaching = TRUE;
+
+	return PURPLE_CMD_RET_OK;
+}
+
+static PurpleCmdRet silcpurple_cmd_cmode(PurpleConversation *conv,
+		const char *cmd, char **args, char **error, void *data)
+{
+	PurpleConnection *gc;
+	SilcPurple sg;
+	SilcChannelEntry channel;
+	char *silccmd, *silcargs, *msg, tmp[256];
+	const char *chname;
+
+	gc = purple_conversation_get_gc(conv);
+
+	if (gc == NULL || !args || gc->proto_data == NULL)
+		return PURPLE_CMD_RET_FAILED;
+
+	sg = gc->proto_data;
+
+	if (args[0])
+		chname = args[0];
+	else
+		chname = purple_conversation_get_name(conv);
+
+	if (!args[1]) {
+		channel = silc_client_get_channel(sg->client, sg->conn,
+										  (char *)chname);
+		if (!channel) {
+			*error = g_strdup_printf(_("channel %s not found"), chname);
+			return PURPLE_CMD_RET_FAILED;
+		}
+		if (channel->mode) {
+			silcpurple_get_chmode_string(channel->mode, tmp, sizeof(tmp));
+			msg = g_strdup_printf(_("channel modes for %s: %s"), chname, tmp);
+		} else {
+			msg = g_strdup_printf(_("no channel modes are set on %s"), chname);
+		}
+		purple_conv_chat_write(PURPLE_CONV_CHAT(conv), "",
+							 msg, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NO_LOG, time(NULL));
+		g_free(msg);
+		return PURPLE_CMD_RET_OK;
+	}
+
+	silcargs = g_strjoinv(" ", args);
+	silccmd = g_strconcat(cmd, " ", args ? silcargs : NULL, NULL);
+	g_free(silcargs);
+	if (!silc_client_command_call(sg->client, sg->conn, silccmd)) {
+		g_free(silccmd);
+		*error = g_strdup_printf(_("Failed to set cmodes for %s"), args[0]);
+		return PURPLE_CMD_RET_FAILED;
+	}
+	g_free(silccmd);
+
+	return PURPLE_CMD_RET_OK;
+}
+
+static PurpleCmdRet silcpurple_cmd_generic(PurpleConversation *conv,
+		const char *cmd, char **args, char **error, void *data)
+{
+	PurpleConnection *gc;
+	SilcPurple sg;
+	char *silccmd, *silcargs;
+
+	gc = purple_conversation_get_gc(conv);
+
+	if (gc == NULL)
+		return PURPLE_CMD_RET_FAILED;
+
+	sg = gc->proto_data;
+
+	if (sg == NULL)
+		return PURPLE_CMD_RET_FAILED;
+
+	silcargs = g_strjoinv(" ", args);
+	silccmd = g_strconcat(cmd, " ", args ? silcargs : NULL, NULL);
+	g_free(silcargs);
+	if (!silc_client_command_call(sg->client, sg->conn, silccmd)) {
+		g_free(silccmd);
+		*error = g_strdup_printf(_("Unknown command: %s, (may be a client bug)"), cmd);
+		return PURPLE_CMD_RET_FAILED;
+	}
+	g_free(silccmd);
+
+	return PURPLE_CMD_RET_OK;
+}
+
+static PurpleCmdRet silcpurple_cmd_quit(PurpleConversation *conv,
+		const char *cmd, char **args, char **error, void *data)
+{
+	PurpleConnection *gc;
+	SilcPurple sg;
+
+	gc = purple_conversation_get_gc(conv);
+
+	if (gc == NULL)
+		return PURPLE_CMD_RET_FAILED;
+
+	sg = gc->proto_data;
+
+	if (sg == NULL)
+		return PURPLE_CMD_RET_FAILED;
+
+	silc_client_command_call(sg->client, sg->conn, NULL,
+				 "QUIT", (args && args[0]) ? args[0] : "Download this: " PURPLE_WEBSITE, NULL);
+
+	return PURPLE_CMD_RET_OK;
+}
+
+static PurpleCmdRet silcpurple_cmd_call(PurpleConversation *conv,
+		const char *cmd, char **args, char **error, void *data)
+{
+	PurpleConnection *gc;
+	SilcPurple sg;
+
+	gc = purple_conversation_get_gc(conv);
+
+	if (gc == NULL)
+		return PURPLE_CMD_RET_FAILED;
+
+	sg = gc->proto_data;
+
+	if (sg == NULL)
+		return PURPLE_CMD_RET_FAILED;
+
+	if (!silc_client_command_call(sg->client, sg->conn, args[0])) {
+		*error = g_strdup_printf(_("Unknown command: %s"), args[0]);
+		return PURPLE_CMD_RET_FAILED;
+	}
+
+	return PURPLE_CMD_RET_OK;
+}
+
+
+/************************** Plugin Initialization ****************************/
+
+static void
+silcpurple_register_commands(void)
+{
+	purple_cmd_register("part", "w", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
+			PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS,
+			"prpl-silc", silcpurple_cmd_chat_part, _("part [channel]:  Leave the chat"), NULL);
+	purple_cmd_register("leave", "w", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
+			PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS,
+			"prpl-silc", silcpurple_cmd_chat_part, _("leave [channel]:  Leave the chat"), NULL);
+	purple_cmd_register("topic", "s", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc",
+			silcpurple_cmd_chat_topic, _("topic [&lt;new topic&gt;]:  View or change the topic"), NULL);
+	purple_cmd_register("join", "ws", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
+			PURPLE_CMD_FLAG_PRPL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS,
+			"prpl-silc", silcpurple_cmd_chat_join,
+			_("join &lt;channel&gt; [&lt;password&gt;]:  Join a chat on this network"), NULL);
+	purple_cmd_register("list", "", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc",
+			silcpurple_cmd_chat_list, _("list:  List channels on this network"), NULL);
+	purple_cmd_register("whois", "w", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+			"prpl-silc",
+			silcpurple_cmd_whois, _("whois &lt;nick&gt;:  View nick's information"), NULL);
+	purple_cmd_register("msg", "ws", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+			"prpl-silc", silcpurple_cmd_msg,
+			_("msg &lt;nick&gt; &lt;message&gt;:  Send a private message to a user"), NULL);
+	purple_cmd_register("query", "ws", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_query,
+			_("query &lt;nick&gt; [&lt;message&gt;]:  Send a private message to a user"), NULL);
+	purple_cmd_register("motd", "", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_motd,
+			_("motd:  View the server's Message Of The Day"), NULL);
+	purple_cmd_register("detach", "", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+			"prpl-silc", silcpurple_cmd_detach,
+			_("detach:  Detach this session"), NULL);
+	purple_cmd_register("quit", "s", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_quit,
+			_("quit [message]:  Disconnect from the server, with an optional message"), NULL);
+	purple_cmd_register("call", "s", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+			"prpl-silc", silcpurple_cmd_call,
+			_("call &lt;command&gt;:  Call any silc client command"), NULL);
+	/* These below just get passed through for the silc client library to deal
+	 * with */
+	purple_cmd_register("kill", "ws", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
+			_("kill &lt;nick&gt; [-pubkey|&lt;reason&gt;]:  Kill nick"), NULL);
+	purple_cmd_register("nick", "w", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+			"prpl-silc", silcpurple_cmd_generic,
+			_("nick &lt;newnick&gt;:  Change your nickname"), NULL);
+	purple_cmd_register("whowas", "ww", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
+			_("whowas &lt;nick&gt;:  View nick's information"), NULL);
+	purple_cmd_register("cmode", "wws", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_cmode,
+			_("cmode &lt;channel&gt; [+|-&lt;modes&gt;] [arguments]:  Change or display channel modes"), NULL);
+	purple_cmd_register("cumode", "wws", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
+			_("cumode &lt;channel&gt; +|-&lt;modes&gt; &lt;nick&gt;:  Change nick's modes on channel"), NULL);
+	purple_cmd_register("umode", "w", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+			"prpl-silc", silcpurple_cmd_generic,
+			_("umode &lt;usermodes&gt;:  Set your modes in the network"), NULL);
+	purple_cmd_register("oper", "s", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+			"prpl-silc", silcpurple_cmd_generic,
+			_("oper &lt;nick&gt; [-pubkey]:  Get server operator privileges"), NULL);
+	purple_cmd_register("invite", "ws", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
+			_("invite &lt;channel&gt; [-|+]&lt;nick&gt;:  invite nick or add/remove from channel invite list"), NULL);
+	purple_cmd_register("kick", "wws", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
+			_("kick &lt;channel&gt; &lt;nick&gt; [comment]:  Kick client from channel"), NULL);
+	purple_cmd_register("info", "w", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
+			_("info [server]:  View server administrative details"), NULL);
+	purple_cmd_register("ban", "ww", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
+			_("ban [&lt;channel&gt; +|-&lt;nick&gt;]:  Ban client from channel"), NULL);
+	purple_cmd_register("getkey", "w", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+			"prpl-silc", silcpurple_cmd_generic,
+			_("getkey &lt;nick|server&gt;:  Retrieve client's or server's public key"), NULL);
+	purple_cmd_register("stats", "", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+			"prpl-silc", silcpurple_cmd_generic,
+			_("stats:  View server and network statistics"), NULL);
+	purple_cmd_register("ping", "", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+			"prpl-silc", silcpurple_cmd_generic,
+			_("ping:  Send PING to the connected server"), NULL);
+#if 0 /* Purple doesn't handle these yet */
+	purple_cmd_register("users", "w", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
+			"prpl-silc", silcpurple_cmd_users,
+			_("users &lt;channel&gt;:  List users in channel"));
+	purple_cmd_register("names", "ww", PURPLE_CMD_P_PRPL,
+			PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
+			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_names,
+			_("names [-count|-ops|-halfops|-voices|-normal] &lt;channel(s)&gt;:  List specific users in channel(s)"));
+#endif
+}
+
+static PurpleWhiteboardPrplOps silcpurple_wb_ops =
+{
+	silcpurple_wb_start,
+	silcpurple_wb_end,
+	silcpurple_wb_get_dimensions,
+	silcpurple_wb_set_dimensions,
+	silcpurple_wb_get_brush,
+	silcpurple_wb_set_brush,
+	silcpurple_wb_send,
+	silcpurple_wb_clear,
+
+	/* padding */
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+static PurplePluginProtocolInfo prpl_info =
+{
+#ifdef HAVE_SILCMIME_H
+	OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME |
+	OPT_PROTO_PASSWORD_OPTIONAL | OPT_PROTO_IM_IMAGE,
+#else
+	OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME |
+	OPT_PROTO_PASSWORD_OPTIONAL,
+#endif
+	NULL,						/* user_splits */
+	NULL,						/* protocol_options */
+#ifdef SILC_ATTRIBUTE_USER_ICON
+	{"jpeg,gif,png,bmp", 0, 0, 96, 96, 0, PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */
+#else
+	NO_BUDDY_ICONS,
+#endif
+	silcpurple_list_icon,			/* list_icon */
+	NULL,				/* list_emblems */
+	silcpurple_status_text,		/* status_text */
+	silcpurple_tooltip_text,		/* tooltip_text */
+	silcpurple_away_states,		/* away_states */
+	silcpurple_blist_node_menu,	/* blist_node_menu */
+	silcpurple_chat_info,			/* chat_info */
+	silcpurple_chat_info_defaults,/* chat_info_defaults */
+	silcpurple_login,				/* login */
+	silcpurple_close,				/* close */
+	silcpurple_send_im,			/* send_im */
+	silcpurple_set_info,			/* set_info */
+	NULL,						/* send_typing */
+	silcpurple_get_info,			/* get_info */
+	silcpurple_set_status,		/* set_status */
+	silcpurple_idle_set,			/* set_idle */
+	silcpurple_change_passwd,		/* change_passwd */
+	silcpurple_add_buddy,			/* add_buddy */
+	NULL,						/* add_buddies */
+	silcpurple_remove_buddy,		/* remove_buddy */
+	NULL,						/* remove_buddies */
+	NULL,						/* add_permit */
+	NULL,						/* add_deny */
+	NULL,						/* rem_permit */
+	NULL,						/* rem_deny */
+	NULL,						/* set_permit_deny */
+	silcpurple_chat_join,			/* join_chat */
+	NULL,						/* reject_chat */
+	silcpurple_get_chat_name,		/* get_chat_name */
+	silcpurple_chat_invite,		/* chat_invite */
+	silcpurple_chat_leave,		/* chat_leave */
+	NULL,						/* chat_whisper */
+	silcpurple_chat_send,			/* chat_send */
+	silcpurple_keepalive,			/* keepalive */
+	NULL,						/* register_user */
+	NULL,						/* get_cb_info */
+	NULL,						/* get_cb_away */
+	NULL,						/* alias_buddy */
+	NULL,						/* group_buddy */
+	NULL,						/* rename_group */
+	NULL,						/* buddy_free */
+	NULL,						/* convo_closed */
+	NULL,						/* normalize */
+#ifdef SILC_ATTRIBUTE_USER_ICON
+	silcpurple_buddy_set_icon,			/* set_buddy_icon */
+#else
+	NULL,
+#endif
+	NULL,						/* remove_group */
+	NULL,						/* get_cb_real_name */
+	silcpurple_chat_set_topic,	/* set_chat_topic */
+	NULL,						/* find_blist_chat */
+	silcpurple_roomlist_get_list,	/* roomlist_get_list */
+	silcpurple_roomlist_cancel,	/* roomlist_cancel */
+	NULL,						/* roomlist_expand_category */
+	NULL,						/* can_receive_file */
+	silcpurple_ftp_send_file,		/* send_file */
+	silcpurple_ftp_new_xfer,		/* new_xfer */
+	NULL,						/* offline_message */
+	&silcpurple_wb_ops,			/* whiteboard_prpl_ops */
+	NULL,                       /* send_raw */
+	NULL,                       /* roomlist_room_serialize */
+
+	/* padding */
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+static PurplePluginInfo info =
+{
+	PURPLE_PLUGIN_MAGIC,
+	PURPLE_MAJOR_VERSION,
+	PURPLE_MINOR_VERSION,
+	PURPLE_PLUGIN_PROTOCOL,                             /**< type           */
+	NULL,                                             /**< ui_requirement */
+	0,                                                /**< flags          */
+	NULL,                                             /**< dependencies   */
+	PURPLE_PRIORITY_DEFAULT,                            /**< priority       */
+
+	"prpl-silc",                                      /**< id             */
+	"SILC",                                           /**< name           */
+	"1.0",                                            /**< version        */
+	/**  summary        */
+	N_("SILC Protocol Plugin"),
+	/**  description    */
+	N_("Secure Internet Live Conferencing (SILC) Protocol"),
+	"Pekka Riikonen",                                 /**< author         */
+	"http://silcnet.org/",                            /**< homepage       */
+
+	NULL,                                             /**< load           */
+	NULL,                                             /**< unload         */
+	NULL,                                             /**< destroy        */
+
+	NULL,                                             /**< ui_info        */
+	&prpl_info,                                       /**< extra_info     */
+	NULL,                                             /**< prefs_info     */
+	silcpurple_actions,
+
+	/* padding */
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+static void
+init_plugin(PurplePlugin *plugin)
+{
+	PurpleAccountOption *option;
+	PurpleAccountUserSplit *split;
+	char tmp[256];
+	int i;
+	PurpleKeyValuePair *kvp;
+	GList *list = NULL;
+
+	silc_plugin = plugin;
+
+	split = purple_account_user_split_new(_("Network"), "silcnet.org", '@');
+	prpl_info.user_splits = g_list_append(prpl_info.user_splits, split);
+
+	/* Account options */
+	option = purple_account_option_string_new(_("Connect server"),
+						"server",
+						"silc.silcnet.org");
+	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	option = purple_account_option_int_new(_("Port"), "port", 706);
+	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	g_snprintf(tmp, sizeof(tmp), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir());
+	option = purple_account_option_string_new(_("Public Key file"),
+						"public-key", tmp);
+	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	g_snprintf(tmp, sizeof(tmp), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir());
+	option = purple_account_option_string_new(_("Private Key file"),
+						"private-key", tmp);
+	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+
+	for (i = 0; silc_default_ciphers[i].name; i++) {
+		kvp = g_new0(PurpleKeyValuePair, 1);
+		kvp->key = g_strdup(silc_default_ciphers[i].name);
+		kvp->value = g_strdup(silc_default_ciphers[i].name);
+		list = g_list_append(list, kvp);
+	}
+	option = purple_account_option_list_new(_("Cipher"), "cipher", list);
+	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+
+	list = NULL;
+	for (i = 0; silc_default_hmacs[i].name; i++) {
+		kvp = g_new0(PurpleKeyValuePair, 1);
+		kvp->key = g_strdup(silc_default_hmacs[i].name);
+		kvp->value = g_strdup(silc_default_hmacs[i].name);
+		list = g_list_append(list, kvp);
+	}
+	option = purple_account_option_list_new(_("HMAC"), "hmac", list);
+	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+
+	option = purple_account_option_bool_new(_("Public key authentication"),
+					      "pubkey-auth", FALSE);
+	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	option = purple_account_option_bool_new(_("Block IMs without Key Exchange"),
+					      "block-ims", FALSE);
+	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	option = purple_account_option_bool_new(_("Block messages to whiteboard"),
+					      "block-wb", FALSE);
+	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	option = purple_account_option_bool_new(_("Automatically open whiteboard"),
+					      "open-wb", FALSE);
+	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	option = purple_account_option_bool_new(_("Digitally sign and verify all messages"),
+					      "sign-verify", FALSE);
+	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+
+	purple_prefs_remove("/plugins/prpl/silc");
+
+	silcpurple_register_commands();
+
+#ifdef _WIN32
+	silc_net_win32_init();
+#endif
+}
+
+PURPLE_INIT_PLUGIN(silc, init_plugin, info);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/silc10/silcpurple.h	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,173 @@
+/*
+
+  silcpurple.h
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2004 Pekka Riikonen
+
+  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; version 2 of the License.
+
+  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.
+
+*/
+
+#ifndef SILCPURPLE_H
+#define SILCPURPLE_H
+
+/* Purple includes */
+#include "internal.h"
+#include "account.h"
+#include "accountopt.h"
+#include "cmds.h"
+#include "conversation.h"
+#include "debug.h"
+#include "ft.h"
+#include "notify.h"
+#include "prpl.h"
+#include "request.h"
+#include "roomlist.h"
+#include "server.h"
+#include "util.h"
+
+/* Default public and private key file names */
+#define SILCPURPLE_PUBLIC_KEY_NAME "public_key.pub"
+#define SILCPURPLE_PRIVATE_KEY_NAME "private_key.prv"
+
+/* Default settings for creating key pair */
+#define SILCPURPLE_DEF_PKCS "rsa"
+#define SILCPURPLE_DEF_PKCS_LEN 2048
+
+#define SILCPURPLE_PRVGRP 0x001fffff
+
+/* Status IDs */
+#define SILCPURPLE_STATUS_ID_OFFLINE	"offline"
+#define SILCPURPLE_STATUS_ID_AVAILABLE "available"
+#define SILCPURPLE_STATUS_ID_HYPER	"hyper"
+#define SILCPURPLE_STATUS_ID_AWAY		"away"
+#define SILCPURPLE_STATUS_ID_BUSY		"busy"
+#define SILCPURPLE_STATUS_ID_INDISPOSED "indisposed"
+#define SILCPURPLE_STATUS_ID_PAGE		"page"
+
+typedef struct {
+	unsigned long id;
+	const char *channel;
+	unsigned long chid;
+	const char *parentch;
+	SilcChannelPrivateKey key;
+} *SilcPurplePrvgrp;
+
+/* The SILC Purple plugin context */
+typedef struct SilcPurpleStruct {
+	SilcClient client;
+	SilcClientConnection conn;
+
+	guint scheduler;
+	PurpleConnection *gc;
+	PurpleAccount *account;
+	unsigned long channel_ids;
+	GList *grps;
+
+	char *motd;
+	PurpleRoomlist *roomlist;
+#ifdef HAVE_SILCMIME_H
+	SilcMimeAssembler mimeass;
+#endif
+	unsigned int detaching            : 1;
+	unsigned int resuming             : 1;
+	unsigned int roomlist_canceled    : 1;
+	unsigned int chpk                 : 1;
+} *SilcPurple;
+
+
+gboolean silcpurple_check_silc_dir(PurpleConnection *gc);
+void silcpurple_chat_join_done(SilcClient client,
+			     SilcClientConnection conn,
+			     SilcClientEntry *clients,
+			     SilcUInt32 clients_count,
+			     void *context);
+const char *silcpurple_silcdir(void);
+const char *silcpurple_session_file(const char *account);
+void silcpurple_verify_public_key(SilcClient client, SilcClientConnection conn,
+				const char *name, SilcSocketType conn_type,
+				unsigned char *pk, SilcUInt32 pk_len,
+				SilcSKEPKType pk_type,
+				SilcVerifyPublicKey completion, void *context);
+GList *silcpurple_buddy_menu(PurpleBuddy *buddy);
+void silcpurple_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group);
+void silcpurple_send_buddylist(PurpleConnection *gc);
+void silcpurple_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group);
+void silcpurple_buddy_keyagr_request(SilcClient client,
+				   SilcClientConnection conn,
+				   SilcClientEntry client_entry,
+				   const char *hostname, SilcUInt16 port);
+void silcpurple_idle_set(PurpleConnection *gc, int idle);
+void silcpurple_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full);
+char *silcpurple_status_text(PurpleBuddy *b);
+gboolean silcpurple_ip_is_private(const char *ip);
+void silcpurple_ftp_send_file(PurpleConnection *gc, const char *name, const char *file);
+PurpleXfer *silcpurple_ftp_new_xfer(PurpleConnection *gc, const char *name);
+void silcpurple_ftp_request(SilcClient client, SilcClientConnection conn,
+			  SilcClientEntry client_entry, SilcUInt32 session_id,
+			  const char *hostname, SilcUInt16 port);
+void silcpurple_show_public_key(SilcPurple sg,
+			      const char *name, SilcPublicKey public_key,
+			      GCallback callback, void *context);
+void silcpurple_get_info(PurpleConnection *gc, const char *who);
+SilcAttributePayload
+silcpurple_get_attr(SilcDList attrs, SilcAttribute attribute);
+void silcpurple_get_umode_string(SilcUInt32 mode, char *buf,
+			       SilcUInt32 buf_size);
+void silcpurple_get_chmode_string(SilcUInt32 mode, char *buf,
+				SilcUInt32 buf_size);
+void silcpurple_get_chumode_string(SilcUInt32 mode, char *buf,
+				 SilcUInt32 buf_size);
+GList *silcpurple_chat_info(PurpleConnection *gc);
+GHashTable *silcpurple_chat_info_defaults(PurpleConnection *gc, const char *chat_name);
+GList *silcpurple_chat_menu(PurpleChat *);
+void silcpurple_chat_join(PurpleConnection *gc, GHashTable *data);
+char *silcpurple_get_chat_name(GHashTable *data);
+void silcpurple_chat_invite(PurpleConnection *gc, int id, const char *msg,
+			  const char *name);
+void silcpurple_chat_leave(PurpleConnection *gc, int id);
+int silcpurple_chat_send(PurpleConnection *gc, int id, const char *msg, PurpleMessageFlags flags);
+void silcpurple_chat_set_topic(PurpleConnection *gc, int id, const char *topic);
+PurpleRoomlist *silcpurple_roomlist_get_list(PurpleConnection *gc);
+void silcpurple_roomlist_cancel(PurpleRoomlist *list);
+void silcpurple_chat_chauth_show(SilcPurple sg, SilcChannelEntry channel,
+			       SilcBuffer channel_pubkeys);
+void silcpurple_parse_attrs(SilcDList attrs, char **moodstr, char **statusstr,
+					 char **contactstr, char **langstr, char **devicestr,
+					 char **tzstr, char **geostr);
+#ifdef SILC_ATTRIBUTE_USER_ICON
+void silcpurple_buddy_set_icon(PurpleConnection *gc, PurpleStoredImage *img);
+#endif
+#ifdef HAVE_SILCMIME_H
+char *silcpurple_file2mime(const char *filename);
+SilcDList silcpurple_image_message(const char *msg, SilcUInt32 *mflags);
+#endif
+
+#ifdef _WIN32
+typedef int uid_t;
+
+struct passwd {
+	char	*pw_name;	/* user name */
+	char	*pw_passwd;	/* user password */
+	int		pw_uid;		/* user id */
+	int		pw_gid;		/* group id */
+	char	*pw_gecos;	/* real name */
+	char	*pw_dir;	/* home directory */
+	char	*pw_shell;	/* shell program */
+};
+
+struct passwd *getpwuid(int uid);
+int getuid(void);
+int geteuid(void);
+#endif
+
+#endif /* SILCPURPLE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/silc10/util.c	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,771 @@
+/*
+
+  silcpurple_util.c
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2004 - 2005 Pekka Riikonen
+
+  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; version 2 of the License.
+
+  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.
+
+*/
+
+#include "silcincludes.h"
+#include "silcclient.h"
+#include "silcpurple.h"
+#include "imgstore.h"
+
+/**************************** Utility Routines *******************************/
+
+static char str[256], str2[256];
+
+const char *silcpurple_silcdir(void)
+{
+	const char *hd = purple_home_dir();
+	memset(str, 0, sizeof(str));
+	g_snprintf(str, sizeof(str) - 1, "%s" G_DIR_SEPARATOR_S ".silc", hd ? hd : "/tmp");
+	return (const char *)str;
+}
+
+const char *silcpurple_session_file(const char *account)
+{
+	memset(str2, 0, sizeof(str2));
+	g_snprintf(str2, sizeof(str2) - 1, "%s" G_DIR_SEPARATOR_S "%s_session",
+		   silcpurple_silcdir(), account);
+	return (const char *)str2;
+}
+
+gboolean silcpurple_ip_is_private(const char *ip)
+{
+	if (silc_net_is_ip4(ip)) {
+		if (!strncmp(ip, "10.", 3)) {
+			return TRUE;
+		} else if (!strncmp(ip, "172.", 4) && strlen(ip) > 6) {
+			char tmp[3];
+			int s;
+			memset(tmp, 0, sizeof(tmp));
+			strncpy(tmp, ip + 4, 2);
+			s = atoi(tmp);
+			if (s >= 16 && s <= 31)
+				return TRUE;
+		} else if (!strncmp(ip, "192.168.", 8)) {
+			return TRUE;
+		}
+	}
+
+	return FALSE;
+}
+
+/* This checks stats for various SILC files and directories. First it
+   checks if ~/.silc directory exist and is owned by the correct user. If
+   it doesn't exist, it will create the directory. After that it checks if
+   user's Public and Private key files exists and creates them if needed. */
+
+gboolean silcpurple_check_silc_dir(PurpleConnection *gc)
+{
+	char filename[256], file_public_key[256], file_private_key[256];
+	char servfilename[256], clientfilename[256], friendsfilename[256];
+	char pkd[256], prd[256];
+	struct stat st;
+	struct passwd *pw;
+	int fd;
+
+	pw = getpwuid(getuid());
+	if (!pw) {
+		purple_debug_error("silc", "silc: %s\n", strerror(errno));
+		return FALSE;
+	}
+
+	g_snprintf(filename, sizeof(filename) - 1, "%s", silcpurple_silcdir());
+	g_snprintf(servfilename, sizeof(servfilename) - 1, "%s" G_DIR_SEPARATOR_S "serverkeys",
+		   silcpurple_silcdir());
+	g_snprintf(clientfilename, sizeof(clientfilename) - 1, "%s" G_DIR_SEPARATOR_S "clientkeys",
+		   silcpurple_silcdir());
+	g_snprintf(friendsfilename, sizeof(friendsfilename) - 1, "%s" G_DIR_SEPARATOR_S "friends",
+		   silcpurple_silcdir());
+
+	/*
+	 * Check ~/.silc directory
+	 */
+	if ((g_stat(filename, &st)) == -1) {
+		/* If dir doesn't exist */
+		if (errno == ENOENT) {
+			if (pw->pw_uid == geteuid()) {
+				if ((g_mkdir(filename, 0755)) == -1) {
+					purple_debug_error("silc", "Couldn't create '%s' directory\n", filename);
+					return FALSE;
+				}
+			} else {
+				purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
+					filename);
+				return FALSE;
+			}
+		} else {
+			purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n", filename, strerror(errno));
+			return FALSE;
+		}
+	} else {
+#ifndef _WIN32
+		/* Check the owner of the dir */
+		if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
+			purple_debug_error("silc", "You don't seem to own '%s' directory\n",
+				filename);
+			return FALSE;
+		}
+#endif
+	}
+
+	/*
+	 * Check ~./silc/serverkeys directory
+	 */
+	if ((g_stat(servfilename, &st)) == -1) {
+		/* If dir doesn't exist */
+		if (errno == ENOENT) {
+			if (pw->pw_uid == geteuid()) {
+				if ((g_mkdir(servfilename, 0755)) == -1) {
+					purple_debug_error("silc", "Couldn't create '%s' directory\n", servfilename);
+					return FALSE;
+				}
+			} else {
+				purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
+					servfilename);
+				return FALSE;
+			}
+		} else {
+			purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n",
+							 servfilename, strerror(errno));
+			return FALSE;
+		}
+	}
+
+	/*
+	 * Check ~./silc/clientkeys directory
+	 */
+	if ((g_stat(clientfilename, &st)) == -1) {
+		/* If dir doesn't exist */
+		if (errno == ENOENT) {
+			if (pw->pw_uid == geteuid()) {
+				if ((g_mkdir(clientfilename, 0755)) == -1) {
+					purple_debug_error("silc", "Couldn't create '%s' directory\n", clientfilename);
+					return FALSE;
+				}
+			} else {
+				purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
+					clientfilename);
+				return FALSE;
+			}
+		} else {
+			purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n",
+							 clientfilename, strerror(errno));
+			return FALSE;
+		}
+	}
+
+	/*
+	 * Check ~./silc/friends directory
+	 */
+	if ((g_stat(friendsfilename, &st)) == -1) {
+		/* If dir doesn't exist */
+		if (errno == ENOENT) {
+			if (pw->pw_uid == geteuid()) {
+				if ((g_mkdir(friendsfilename, 0755)) == -1) {
+					purple_debug_error("silc", "Couldn't create '%s' directory\n", friendsfilename);
+					return FALSE;
+				}
+			} else {
+				purple_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
+					friendsfilename);
+				return FALSE;
+			}
+		} else {
+			purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n",
+							 friendsfilename, strerror(errno));
+			return FALSE;
+		}
+	}
+
+	/*
+	 * Check Public and Private keys
+	 */
+	g_snprintf(pkd, sizeof(pkd), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir());
+	g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir());
+	g_snprintf(file_public_key, sizeof(file_public_key) - 1, "%s",
+		   purple_account_get_string(gc->account, "public-key", pkd));
+	g_snprintf(file_private_key, sizeof(file_public_key) - 1, "%s",
+		   purple_account_get_string(gc->account, "private-key", prd));
+
+	if ((g_stat(file_public_key, &st)) == -1) {
+		/* If file doesn't exist */
+		if (errno == ENOENT) {
+			purple_connection_update_progress(gc, _("Creating SILC key pair..."), 1, 5);
+			if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS,
+					     SILCPURPLE_DEF_PKCS_LEN,
+					     file_public_key, file_private_key, NULL,
+					     (gc->password == NULL) ? "" : gc->password,
+						 NULL, NULL, NULL, FALSE)) {
+				purple_debug_error("silc", "Couldn't create key pair\n");
+				return FALSE;
+			}
+
+			if ((g_stat(file_public_key, &st)) == -1) {
+				purple_debug_error("silc", "Couldn't stat '%s' public key, error: %s\n",
+					file_public_key, strerror(errno));
+				return FALSE;
+			}
+		} else {
+			purple_debug_error("silc", "Couldn't stat '%s' public key, error: %s\n",
+							 file_public_key, strerror(errno));
+			return FALSE;
+		}
+	}
+
+#ifndef _WIN32
+	/* Check the owner of the public key */
+	if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
+		purple_debug_error("silc", "You don't seem to own your public key!?\n");
+		return FALSE;
+	}
+#endif
+
+	if ((fd = g_open(file_private_key, O_RDONLY, 0)) != -1) {
+		if ((fstat(fd, &st)) == -1) {
+			purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n",
+							 file_private_key, strerror(errno));
+			close(fd);
+			return FALSE;
+		}
+	} else if ((g_stat(file_private_key, &st)) == -1) {
+		/* If file doesn't exist */
+		if (errno == ENOENT) {
+			purple_connection_update_progress(gc, _("Creating SILC key pair..."), 1, 5);
+			if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS,
+					     SILCPURPLE_DEF_PKCS_LEN,
+					     file_public_key, file_private_key, NULL,
+					     (gc->password == NULL) ? "" : gc->password,
+						 NULL, NULL, NULL, FALSE)) {
+				purple_debug_error("silc", "Couldn't create key pair\n");
+				return FALSE;
+			}
+
+			if ((fd = g_open(file_private_key, O_RDONLY, 0)) != -1) {
+				if ((fstat(fd, &st)) == -1) {
+					purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n",
+							 file_private_key, strerror(errno));
+					close(fd);
+					return FALSE;
+				}
+			}
+			/* This shouldn't really happen because silc_create_key_pair()
+			 * will set the permissions */
+			else if ((g_stat(file_private_key, &st)) == -1) {
+				purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n",
+					file_private_key, strerror(errno));
+				return FALSE;
+			}
+		} else {
+			purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n",
+							 file_private_key, strerror(errno));
+			return FALSE;
+		}
+	}
+
+#ifndef _WIN32
+	/* Check the owner of the private key */
+	if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
+		purple_debug_error("silc", "You don't seem to own your private key!?\n");
+		if (fd != -1)
+			close(fd);
+		return FALSE;
+	}
+
+	/* Check the permissions for the private key */
+	if ((st.st_mode & 0777) != 0600) {
+		purple_debug_warning("silc", "Wrong permissions in your private key file `%s'!\n"
+			"Trying to change them ...\n", file_private_key);
+		if ((fd == -1) || (fchmod(fd, S_IRUSR | S_IWUSR)) == -1) {
+			purple_debug_error("silc",
+				"Failed to change permissions for private key file!\n"
+				"Permissions for your private key file must be 0600.\n");
+			if (fd != -1)
+				close(fd);
+			return FALSE;
+		}
+		purple_debug_warning("silc", "Done.\n\n");
+	}
+#endif
+
+	if (fd != -1)
+		close(fd);
+
+	return TRUE;
+}
+
+#ifdef _WIN32
+struct passwd *getpwuid(uid_t uid) {
+	struct passwd *pwd = calloc(1, sizeof(struct passwd));
+	return pwd;
+}
+
+uid_t getuid() {
+	return 0;
+}
+
+uid_t geteuid() {
+	return 0;
+}
+#endif
+
+void silcpurple_show_public_key(SilcPurple sg,
+			      const char *name, SilcPublicKey public_key,
+			      GCallback callback, void *context)
+{
+	SilcPublicKeyIdentifier ident;
+	SilcPKCS pkcs;
+	char *fingerprint, *babbleprint;
+	unsigned char *pk;
+	SilcUInt32 pk_len, key_len = 0;
+	GString *s;
+	char *buf;
+
+	ident = silc_pkcs_decode_identifier(public_key->identifier);
+	if (!ident)
+		return;
+
+	pk = silc_pkcs_public_key_encode(public_key, &pk_len);
+	fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
+	babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
+
+	if (silc_pkcs_alloc((unsigned char *)public_key->name, &pkcs)) {
+		key_len = silc_pkcs_public_key_set(pkcs, public_key);
+		silc_pkcs_free(pkcs);
+	}
+
+	s = g_string_new("");
+	if (ident->realname)
+		/* Hint for translators: Please check the tabulator width here and in
+		   the next strings (short strings: 2 tabs, longer strings 1 tab,
+		   sum: 3 tabs or 24 characters) */
+		g_string_append_printf(s, _("Real Name: \t%s\n"), ident->realname);
+	if (ident->username)
+		g_string_append_printf(s, _("User Name: \t%s\n"), ident->username);
+	if (ident->email)
+		g_string_append_printf(s, _("E-Mail: \t\t%s\n"), ident->email);
+	if (ident->host)
+		g_string_append_printf(s, _("Host Name: \t%s\n"), ident->host);
+	if (ident->org)
+		g_string_append_printf(s, _("Organization: \t%s\n"), ident->org);
+	if (ident->country)
+		g_string_append_printf(s, _("Country: \t%s\n"), ident->country);
+	g_string_append_printf(s, _("Algorithm: \t%s\n"), public_key->name);
+	g_string_append_printf(s, _("Key Length: \t%d bits\n"), (int)key_len);
+	g_string_append_printf(s, "\n");
+	g_string_append_printf(s, _("Public Key Fingerprint:\n%s\n\n"), fingerprint);
+	g_string_append_printf(s, _("Public Key Babbleprint:\n%s"), babbleprint);
+
+	buf = g_string_free(s, FALSE);
+
+	purple_request_action(sg->gc, _("Public Key Information"),
+			    _("Public Key Information"),
+			    buf, 0, purple_connection_get_account(sg->gc),
+				NULL, NULL, context, 1, _("Close"), callback);
+
+	g_free(buf);
+	silc_free(fingerprint);
+	silc_free(babbleprint);
+	silc_free(pk);
+	silc_pkcs_free_identifier(ident);
+}
+
+SilcAttributePayload
+silcpurple_get_attr(SilcDList attrs, SilcAttribute attribute)
+{
+	SilcAttributePayload attr = NULL;
+
+	if (!attrs)
+		return NULL;
+
+	silc_dlist_start(attrs);
+	while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END)
+		if (attribute == silc_attribute_get_attribute(attr))
+			break;
+
+	return attr;
+}
+
+void silcpurple_get_umode_string(SilcUInt32 mode, char *buf,
+			       SilcUInt32 buf_size)
+{
+	memset(buf, 0, buf_size);
+	if ((mode & SILC_UMODE_SERVER_OPERATOR) ||
+	    (mode & SILC_UMODE_ROUTER_OPERATOR)) {
+		strcat(buf, (mode & SILC_UMODE_SERVER_OPERATOR) ?
+		       "[server operator] " :
+		       (mode & SILC_UMODE_ROUTER_OPERATOR) ?
+		       "[SILC operator] " : "[unknown mode] ");
+	}
+	if (mode & SILC_UMODE_GONE)
+		strcat(buf, "[away] ");
+	if (mode & SILC_UMODE_INDISPOSED)
+		strcat(buf, "[indisposed] ");
+	if (mode & SILC_UMODE_BUSY)
+		strcat(buf, "[busy] ");
+	if (mode & SILC_UMODE_PAGE)
+		strcat(buf, "[wake me up] ");
+	if (mode & SILC_UMODE_HYPER)
+		strcat(buf, "[hyperactive] ");
+	if (mode & SILC_UMODE_ROBOT)
+		strcat(buf, "[robot] ");
+	if (mode & SILC_UMODE_ANONYMOUS)
+		strcat(buf, "[anonymous] ");
+	if (mode & SILC_UMODE_BLOCK_PRIVMSG)
+		strcat(buf, "[blocks private messages] ");
+	if (mode & SILC_UMODE_DETACHED)
+		strcat(buf, "[detached] ");
+	if (mode & SILC_UMODE_REJECT_WATCHING)
+		strcat(buf, "[rejects watching] ");
+	if (mode & SILC_UMODE_BLOCK_INVITE)
+		strcat(buf, "[blocks invites] ");
+}
+
+void silcpurple_get_chmode_string(SilcUInt32 mode, char *buf,
+				SilcUInt32 buf_size)
+{
+	memset(buf, 0, buf_size);
+	if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
+		strcat(buf, "[permanent] ");
+	if (mode & SILC_CHANNEL_MODE_PRIVATE)
+		strcat(buf, "[private] ");
+	if (mode & SILC_CHANNEL_MODE_SECRET)
+		strcat(buf, "[secret] ");
+	if (mode & SILC_CHANNEL_MODE_PRIVKEY)
+		strcat(buf, "[private key] ");
+	if (mode & SILC_CHANNEL_MODE_INVITE)
+		strcat(buf, "[invite only] ");
+	if (mode & SILC_CHANNEL_MODE_TOPIC)
+		strcat(buf, "[topic restricted] ");
+	if (mode & SILC_CHANNEL_MODE_ULIMIT)
+		strcat(buf, "[user count limit] ");
+	if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
+		strcat(buf, "[passphrase auth] ");
+	if (mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)
+		strcat(buf, "[public key auth] ");
+	if (mode & SILC_CHANNEL_MODE_SILENCE_USERS)
+		strcat(buf, "[users silenced] ");
+	if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS)
+		strcat(buf, "[operators silenced] ");
+}
+
+void silcpurple_get_chumode_string(SilcUInt32 mode, char *buf,
+				 SilcUInt32 buf_size)
+{
+	memset(buf, 0, buf_size);
+	if (mode & SILC_CHANNEL_UMODE_CHANFO)
+		strcat(buf, "[founder] ");
+	if (mode & SILC_CHANNEL_UMODE_CHANOP)
+		strcat(buf, "[operator] ");
+	if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)
+		strcat(buf, "[blocks messages] ");
+	if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)
+		strcat(buf, "[blocks user messages] ");
+	if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)
+		strcat(buf, "[blocks robot messages] ");
+	if (mode & SILC_CHANNEL_UMODE_QUIET)
+		strcat(buf, "[quieted] ");
+}
+
+void
+silcpurple_parse_attrs(SilcDList attrs, char **moodstr, char **statusstr,
+					 char **contactstr, char **langstr, char **devicestr,
+					 char **tzstr, char **geostr)
+{
+	SilcAttributePayload attr;
+	SilcAttributeMood mood = 0;
+	SilcAttributeContact contact;
+	SilcAttributeObjDevice device;
+	SilcAttributeObjGeo geo;
+
+	char tmp[1024];
+	GString *s;
+
+	*moodstr = NULL;
+	*statusstr = NULL;
+	*contactstr = NULL;
+	*langstr = NULL;
+	*devicestr = NULL;
+	*tzstr = NULL;
+	*geostr = NULL;
+
+	if (!attrs)
+		return;
+
+	s = g_string_new("");
+	attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_STATUS_MOOD);
+	if (attr && silc_attribute_get_object(attr, &mood, sizeof(mood))) {
+		if (mood & SILC_ATTRIBUTE_MOOD_HAPPY)
+			g_string_append_printf(s, "[%s] ", _("Happy"));
+		if (mood & SILC_ATTRIBUTE_MOOD_SAD)
+			g_string_append_printf(s, "[%s] ", _("Sad"));
+		if (mood & SILC_ATTRIBUTE_MOOD_ANGRY)
+			g_string_append_printf(s, "[%s] ", _("Angry"));
+		if (mood & SILC_ATTRIBUTE_MOOD_JEALOUS)
+			g_string_append_printf(s, "[%s] ", _("Jealous"));
+		if (mood & SILC_ATTRIBUTE_MOOD_ASHAMED)
+			g_string_append_printf(s, "[%s] ", _("Ashamed"));
+		if (mood & SILC_ATTRIBUTE_MOOD_INVINCIBLE)
+			g_string_append_printf(s, "[%s] ", _("Invincible"));
+		if (mood & SILC_ATTRIBUTE_MOOD_INLOVE)
+			g_string_append_printf(s, "[%s] ", _("In Love"));
+		if (mood & SILC_ATTRIBUTE_MOOD_SLEEPY)
+			g_string_append_printf(s, "[%s] ", _("Sleepy"));
+		if (mood & SILC_ATTRIBUTE_MOOD_BORED)
+			g_string_append_printf(s, "[%s] ", _("Bored"));
+		if (mood & SILC_ATTRIBUTE_MOOD_EXCITED)
+			g_string_append_printf(s, "[%s] ", _("Excited"));
+		if (mood & SILC_ATTRIBUTE_MOOD_ANXIOUS)
+			g_string_append_printf(s, "[%s] ", _("Anxious"));
+	}
+	if (strlen(s->str)) {
+		*moodstr = s->str;
+		g_string_free(s, FALSE);
+	} else
+		g_string_free(s, TRUE);
+
+	attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_STATUS_FREETEXT);
+	memset(tmp, 0, sizeof(tmp));
+	if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp)))
+		*statusstr = g_strdup(tmp);
+
+	s = g_string_new("");
+	attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_PREFERRED_CONTACT);
+	if (attr && silc_attribute_get_object(attr, &contact, sizeof(contact))) {
+		if (contact & SILC_ATTRIBUTE_CONTACT_CHAT)
+			g_string_append_printf(s, "[%s] ", _("Chat"));
+		if (contact & SILC_ATTRIBUTE_CONTACT_EMAIL)
+			g_string_append_printf(s, "[%s] ", _("E-Mail"));
+		if (contact & SILC_ATTRIBUTE_CONTACT_CALL)
+			g_string_append_printf(s, "[%s] ", _("Phone"));
+		if (contact & SILC_ATTRIBUTE_CONTACT_PAGE)
+			g_string_append_printf(s, "[%s] ", _("Paging"));
+		if (contact & SILC_ATTRIBUTE_CONTACT_SMS)
+			g_string_append_printf(s, "[%s] ", _("SMS"));
+		if (contact & SILC_ATTRIBUTE_CONTACT_MMS)
+			g_string_append_printf(s, "[%s] ", _("MMS"));
+		if (contact & SILC_ATTRIBUTE_CONTACT_VIDEO)
+			g_string_append_printf(s, "[%s] ", _("Video Conferencing"));
+	}
+	if (strlen(s->str)) {
+		*contactstr = s->str;
+		g_string_free(s, FALSE);
+	} else
+		g_string_free(s, TRUE);
+
+	attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_PREFERRED_LANGUAGE);
+	memset(tmp, 0, sizeof(tmp));
+	if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp)))
+		*langstr = g_strdup(tmp);
+
+	s = g_string_new("");
+	attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_DEVICE_INFO);
+	memset(&device, 0, sizeof(device));
+	if (attr && silc_attribute_get_object(attr, &device, sizeof(device))) {
+		if (device.type == SILC_ATTRIBUTE_DEVICE_COMPUTER)
+			g_string_append_printf(s, "%s: ", _("Computer"));
+		if (device.type == SILC_ATTRIBUTE_DEVICE_MOBILE_PHONE)
+			g_string_append_printf(s, "%s: ", _("Mobile Phone"));
+		if (device.type == SILC_ATTRIBUTE_DEVICE_PDA)
+			g_string_append_printf(s, "%s: ", _("PDA"));
+		if (device.type == SILC_ATTRIBUTE_DEVICE_TERMINAL)
+			g_string_append_printf(s, "%s: ", _("Terminal"));
+		g_string_append_printf(s, "%s %s %s %s",
+				device.manufacturer ? device.manufacturer : "",
+				device.version ? device.version : "",
+				device.model ? device.model : "",
+				device.language ? device.language : "");
+	}
+	if (strlen(s->str)) {
+		*devicestr = s->str;
+		g_string_free(s, FALSE);
+	} else
+		g_string_free(s, TRUE);
+
+	attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_TIMEZONE);
+	memset(tmp, 0, sizeof(tmp));
+	if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp)))
+		*tzstr = g_strdup(tmp);
+
+	attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_GEOLOCATION);
+	memset(&geo, 0, sizeof(geo));
+	if (attr && silc_attribute_get_object(attr, &geo, sizeof(geo)))
+		*geostr = g_strdup_printf("%s %s %s (%s)",
+				geo.longitude ? geo.longitude : "",
+				geo.latitude ? geo.latitude : "",
+				geo.altitude ? geo.altitude : "",
+				geo.accuracy ? geo.accuracy : "");
+}
+
+#ifdef HAVE_SILCMIME_H
+/* Returns MIME type of filetype */
+
+char *silcpurple_file2mime(const char *filename)
+{
+	const char *ct;
+
+	ct = strrchr(filename, '.');
+	if (!ct)
+		return NULL;
+	else if (!g_ascii_strcasecmp(".png", ct))
+		return strdup("image/png");
+	else if (!g_ascii_strcasecmp(".jpg", ct))
+		return strdup("image/jpeg");
+	else if (!g_ascii_strcasecmp(".jpeg", ct))
+		return strdup("image/jpeg");
+	else if (!g_ascii_strcasecmp(".gif", ct))
+		return strdup("image/gif");
+	else if (!g_ascii_strcasecmp(".tiff", ct))
+		return strdup("image/tiff");
+	
+	return NULL;
+}
+
+/* Checks if message has images, and assembles MIME message if it has. 
+   If only one image is present, creates simple MIME image message.  If 
+   there are multiple images and/or text with images multipart MIME 
+   message is created. */
+
+SilcDList silcpurple_image_message(const char *msg, SilcUInt32 *mflags)
+{
+	SilcMime mime = NULL, p;
+	SilcDList list, parts = NULL;
+	const char *start, *end, *last;
+	GData *attribs;
+	char *type;
+	gboolean images = FALSE;
+
+	last = msg;
+	while (last && *last && purple_markup_find_tag("img", last, &start,
+						     &end, &attribs)) {
+		PurpleStoredImage *image = NULL;
+		const char *id;
+
+		/* Check if there is text before image */
+		if (start - last) {
+			char *text, *tmp;
+			p = silc_mime_alloc();
+
+			/* Add content type */
+			silc_mime_add_field(p, "Content-Type",
+					    "text/plain; charset=utf-8");
+
+			tmp = g_strndup(last, start - last);
+			text = purple_unescape_html(tmp);
+			g_free(tmp);
+			/* Add text */
+			silc_mime_add_data(p, text, strlen(text));
+			g_free(text);
+
+			if (!parts)
+				parts = silc_dlist_init();
+			silc_dlist_add(parts, p);
+		}
+
+		id = g_datalist_get_data(&attribs, "id");
+		if (id && (image = purple_imgstore_find_by_id(atoi(id)))) {
+			unsigned long imglen = purple_imgstore_get_size(image);
+			gconstpointer img = purple_imgstore_get_data(image);
+
+			p = silc_mime_alloc();
+
+			/* Add content type */
+			type = silcpurple_file2mime(purple_imgstore_get_filename(image));
+			if (!type) {
+				g_datalist_clear(&attribs);
+				last = end + 1;
+				continue;
+			}
+			silc_mime_add_field(p, "Content-Type", type);
+			silc_free(type);
+
+			/* Add content transfer encoding */
+			silc_mime_add_field(p, "Content-Transfer-Encoding", "binary");
+
+			/* Add image data */
+			silc_mime_add_data(p, img, imglen);
+
+			if (!parts)
+				parts = silc_dlist_init();
+			silc_dlist_add(parts, p);
+			images = TRUE;
+		}
+
+		g_datalist_clear(&attribs);
+
+		/* Continue after tag */
+		last = end + 1;
+	}
+
+	/* Check for text after the image(s) */
+	if (images && last && *last) {
+		char *tmp = purple_unescape_html(last);
+		p = silc_mime_alloc();
+
+		/* Add content type */
+		silc_mime_add_field(p, "Content-Type",
+				    "text/plain; charset=utf-8");
+
+		/* Add text */
+		silc_mime_add_data(p, tmp, strlen(tmp));
+		g_free(tmp);
+
+		if (!parts)
+			parts = silc_dlist_init();
+		silc_dlist_add(parts, p);
+	}
+
+	/* If there weren't any images, don't return anything. */
+	if (!images) {
+		if (parts)
+			silc_dlist_uninit(parts);
+		return NULL;
+	}
+
+	if (silc_dlist_count(parts) > 1) {
+		/* Multipart MIME message */
+		char b[32];
+		mime = silc_mime_alloc();
+		silc_mime_add_field(mime, "MIME-Version", "1.0");
+		g_snprintf(b, sizeof(b), "b%4X%4X",
+			   (unsigned int)time(NULL),
+			   silc_dlist_count(parts)); 
+		silc_mime_set_multipart(mime, "mixed", b);
+		silc_dlist_start(parts);
+		while ((p = silc_dlist_get(parts)) != SILC_LIST_END)
+			silc_mime_add_multipart(mime, p);
+	} else {
+		/* Simple MIME message */
+		silc_dlist_start(parts);
+		mime = silc_dlist_get(parts);
+		silc_mime_add_field(mime, "MIME-Version", "1.0");
+	}
+
+	*mflags &= ~SILC_MESSAGE_FLAG_UTF8;
+	*mflags |= SILC_MESSAGE_FLAG_DATA;
+
+	/* Encode message. Fragment if it is too large */
+	list = silc_mime_encode_partial(mime, 0xfc00);
+
+	silc_dlist_uninit(parts);
+
+	/* Added multiparts gets freed here */
+	silc_mime_free(mime);
+
+	return list;
+}
+
+#endif /* HAVE_SILCMIME_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/silc10/wb.c	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,517 @@
+/*
+
+  wb.c
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2005 Pekka Riikonen
+
+  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; version 2 of the License.
+
+  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.
+
+*/
+
+#include "silcincludes.h"
+#include "silcclient.h"
+#include "silcpurple.h"
+#include "wb.h"
+
+/*
+  SILC Whiteboard packet:
+
+  1 byte	command
+  2 bytes	width
+  2 bytes	height
+  4 bytes	brush color
+  2 bytes	brush size
+  n bytes	data 
+
+  Data:
+
+  4 bytes	x
+  4 bytes	y
+
+  Commands:
+
+  0x01		draw
+  0x02		clear
+
+  MIME:
+
+  MIME-Version: 1.0
+  Content-Type: application/x-wb
+  Content-Transfer-Encoding: binary
+
+*/
+
+#define SILCPURPLE_WB_MIME "MIME-Version: 1.0\r\nContent-Type: application/x-wb\r\nContent-Transfer-Encoding: binary\r\n\r\n"
+#define SILCPURPLE_WB_HEADER strlen(SILCPURPLE_WB_MIME) + 11
+
+#define SILCPURPLE_WB_WIDTH 500
+#define SILCPURPLE_WB_HEIGHT 400
+#define SILCPURPLE_WB_WIDTH_MAX 1024
+#define SILCPURPLE_WB_HEIGHT_MAX 1024
+
+/* Commands */
+typedef enum {
+	SILCPURPLE_WB_DRAW 	= 0x01,
+	SILCPURPLE_WB_CLEAR	= 0x02,
+} SilcPurpleWbCommand;
+
+/* Brush size */
+typedef enum {
+	SILCPURPLE_WB_BRUSH_SMALL = 2,
+	SILCPURPLE_WB_BRUSH_MEDIUM = 5,
+	SILCPURPLE_WB_BRUSH_LARGE = 10,
+} SilcPurpleWbBrushSize;
+
+/* Brush color (XXX Purple should provide default colors) */
+typedef enum {
+	SILCPURPLE_WB_COLOR_BLACK		= 0,
+	SILCPURPLE_WB_COLOR_RED		= 13369344,
+	SILCPURPLE_WB_COLOR_GREEN		= 52224,
+	SILCPURPLE_WB_COLOR_BLUE		= 204,
+	SILCPURPLE_WB_COLOR_YELLOW 	= 15658496,
+	SILCPURPLE_WB_COLOR_ORANGE	= 16737792,
+	SILCPURPLE_WB_COLOR_CYAN		= 52428,
+	SILCPURPLE_WB_COLOR_VIOLET	= 5381277,
+	SILCPURPLE_WB_COLOR_PURPLE	= 13369548,
+	SILCPURPLE_WB_COLOR_TAN		= 12093547,
+	SILCPURPLE_WB_COLOR_BROWN		= 5256485,
+	SILCPURPLE_WB_COLOR_GREY		= 11184810,
+	SILCPURPLE_WB_COLOR_WHITE		= 16777215,
+} SilcPurpleWbColor;
+
+typedef struct {
+	int type;		/* 0 = buddy, 1 = channel */
+	union {
+		SilcClientEntry client;
+		SilcChannelEntry channel;
+	} u;
+	int width;
+	int height;
+	int brush_size;
+	int brush_color;
+} *SilcPurpleWb;
+
+/* Initialize whiteboard */
+
+PurpleWhiteboard *silcpurple_wb_init(SilcPurple sg, SilcClientEntry client_entry)
+{
+        SilcClientConnection conn;
+	PurpleWhiteboard *wb;
+	SilcPurpleWb wbs;
+
+	conn = sg->conn;
+	wb = purple_whiteboard_get_session(sg->account, client_entry->nickname);
+	if (!wb)
+		wb = purple_whiteboard_create(sg->account, client_entry->nickname, 0);
+	if (!wb)
+		return NULL;
+
+	if (!wb->proto_data) {
+		wbs = silc_calloc(1, sizeof(*wbs));
+		if (!wbs)
+			return NULL;
+		wbs->type = 0;
+		wbs->u.client = client_entry;
+		wbs->width = SILCPURPLE_WB_WIDTH;
+		wbs->height = SILCPURPLE_WB_HEIGHT;
+		wbs->brush_size = SILCPURPLE_WB_BRUSH_SMALL;
+		wbs->brush_color = SILCPURPLE_WB_COLOR_BLACK;
+		wb->proto_data = wbs;
+
+		/* Start the whiteboard */
+		purple_whiteboard_start(wb);
+		purple_whiteboard_clear(wb);
+	}
+
+	return wb;
+}
+
+PurpleWhiteboard *silcpurple_wb_init_ch(SilcPurple sg, SilcChannelEntry channel)
+{
+	PurpleWhiteboard *wb;
+	SilcPurpleWb wbs;
+
+	wb = purple_whiteboard_get_session(sg->account, channel->channel_name);
+	if (!wb)
+		wb = purple_whiteboard_create(sg->account, channel->channel_name, 0);
+	if (!wb)
+		return NULL;
+
+	if (!wb->proto_data) {
+		wbs = silc_calloc(1, sizeof(*wbs));
+		if (!wbs)
+			return NULL;
+		wbs->type = 1;
+		wbs->u.channel = channel;
+		wbs->width = SILCPURPLE_WB_WIDTH;
+		wbs->height = SILCPURPLE_WB_HEIGHT;
+		wbs->brush_size = SILCPURPLE_WB_BRUSH_SMALL;
+		wbs->brush_color = SILCPURPLE_WB_COLOR_BLACK;
+		wb->proto_data = wbs;
+
+		/* Start the whiteboard */
+		purple_whiteboard_start(wb);
+		purple_whiteboard_clear(wb);
+	}
+
+	return wb;
+}
+
+static void
+silcpurple_wb_parse(SilcPurpleWb wbs, PurpleWhiteboard *wb,
+		  unsigned char *message, SilcUInt32 message_len)
+{
+	SilcUInt8 command;
+	SilcUInt16 width, height, brush_size;
+	SilcUInt32 brush_color, x, y, dx, dy;
+	SilcBufferStruct buf;
+	int ret;
+
+	/* Parse the packet */
+	silc_buffer_set(&buf, message, message_len);
+	ret = silc_buffer_unformat(&buf,
+				   SILC_STR_UI_CHAR(&command),
+				   SILC_STR_UI_SHORT(&width),
+				   SILC_STR_UI_SHORT(&height),
+				   SILC_STR_UI_INT(&brush_color),
+				   SILC_STR_UI_SHORT(&brush_size),
+				   SILC_STR_END);
+	if (ret < 0)
+		return;
+	silc_buffer_pull(&buf, ret);
+
+	/* Update whiteboard if its dimensions changed */
+	if (width != wbs->width || height != wbs->height)
+		silcpurple_wb_set_dimensions(wb, height, width);
+
+	if (command == SILCPURPLE_WB_DRAW) {
+		/* Parse data and draw it */
+		ret = silc_buffer_unformat(&buf,
+					   SILC_STR_UI_INT(&dx),
+					   SILC_STR_UI_INT(&dy),
+					   SILC_STR_END);
+		if (ret < 0)
+			return;
+		silc_buffer_pull(&buf, 8);
+		x = dx;
+		y = dy;
+		while (buf.len > 0) {
+			ret = silc_buffer_unformat(&buf,
+						   SILC_STR_UI_INT(&dx),
+						   SILC_STR_UI_INT(&dy),
+						   SILC_STR_END);
+			if (ret < 0)
+				return;
+			silc_buffer_pull(&buf, 8);
+
+			purple_whiteboard_draw_line(wb, x, y, x + dx, y + dy,
+						  brush_color, brush_size);
+			x += dx;
+			y += dy;
+		}
+	}
+
+	if (command == SILCPURPLE_WB_CLEAR)
+		purple_whiteboard_clear(wb);
+}
+
+typedef struct {
+  unsigned char *message;
+  SilcUInt32 message_len;
+  SilcPurple sg;
+  SilcClientEntry sender;
+  SilcChannelEntry channel;
+} *SilcPurpleWbRequest;
+
+static void
+silcpurple_wb_request_cb(SilcPurpleWbRequest req, gint id)
+{
+	PurpleWhiteboard *wb;
+
+        if (id != 1)
+                goto out;
+
+	if (!req->channel)
+		wb = silcpurple_wb_init(req->sg, req->sender);
+	else
+		wb = silcpurple_wb_init_ch(req->sg, req->channel);
+
+	silcpurple_wb_parse(wb->proto_data, wb, req->message, req->message_len);
+
+  out:
+	silc_free(req->message);
+	silc_free(req);
+}
+
+static void
+silcpurple_wb_request(SilcClient client, const unsigned char *message, 
+		    SilcUInt32 message_len, SilcClientEntry sender, 
+		    SilcChannelEntry channel)
+{
+	char tmp[128];
+	SilcPurpleWbRequest req;
+	PurpleConnection *gc;
+	SilcPurple sg;
+
+	gc = client->application;
+	sg = gc->proto_data;
+
+	/* Open whiteboard automatically if requested */
+	if (purple_account_get_bool(sg->account, "open-wb", FALSE)) {
+		PurpleWhiteboard *wb;
+
+		if (!channel)
+			wb = silcpurple_wb_init(sg, sender);
+		else
+			wb = silcpurple_wb_init_ch(sg, channel);
+
+		silcpurple_wb_parse(wb->proto_data, wb, (unsigned char *)message,
+				  message_len);
+		return;
+	}
+
+	if (!channel) {
+		g_snprintf(tmp, sizeof(tmp),
+			_("%s sent message to whiteboard. Would you like "
+			  "to open the whiteboard?"), sender->nickname);
+	} else {
+		g_snprintf(tmp, sizeof(tmp),
+			_("%s sent message to whiteboard on %s channel. "
+			  "Would you like to open the whiteboard?"),
+			sender->nickname, channel->channel_name);
+	}
+
+	req = silc_calloc(1, sizeof(*req));
+	if (!req)
+		return;
+	req->message = silc_memdup(message, message_len);
+	req->message_len = message_len;
+	req->sender = sender;
+	req->channel = channel;
+	req->sg = sg;
+
+	purple_request_action(gc, _("Whiteboard"), tmp, NULL, 1,
+				sg->account, sender->nickname, NULL, req, 2,
+			    _("Yes"), G_CALLBACK(silcpurple_wb_request_cb),
+			    _("No"), G_CALLBACK(silcpurple_wb_request_cb));
+}
+
+/* Process incoming whiteboard message */
+
+void silcpurple_wb_receive(SilcClient client, SilcClientConnection conn,
+			 SilcClientEntry sender, SilcMessagePayload payload,
+			 SilcMessageFlags flags, const unsigned char *message,
+			 SilcUInt32 message_len)
+{
+	SilcPurple sg;
+        PurpleConnection *gc;
+	PurpleWhiteboard *wb;
+	SilcPurpleWb wbs;
+
+	gc = client->application;
+        sg = gc->proto_data;
+
+	wb = purple_whiteboard_get_session(sg->account, sender->nickname);
+	if (!wb) {
+		/* Ask user if they want to open the whiteboard */
+		silcpurple_wb_request(client, message, message_len,
+				    sender, NULL);
+		return;
+	}
+
+	wbs = wb->proto_data;
+	silcpurple_wb_parse(wbs, wb, (unsigned char *)message, message_len);
+}
+
+/* Process incoming whiteboard message on channel */
+
+void silcpurple_wb_receive_ch(SilcClient client, SilcClientConnection conn,
+			    SilcClientEntry sender, SilcChannelEntry channel,
+			    SilcMessagePayload payload,
+			    SilcMessageFlags flags,
+			    const unsigned char *message,
+			    SilcUInt32 message_len)
+{
+	SilcPurple sg;
+        PurpleConnection *gc;
+	PurpleWhiteboard *wb;
+	SilcPurpleWb wbs;
+
+	gc = client->application;
+        sg = gc->proto_data;
+
+	wb = purple_whiteboard_get_session(sg->account, channel->channel_name);
+	if (!wb) {
+		/* Ask user if they want to open the whiteboard */
+		silcpurple_wb_request(client, message, message_len,
+				    sender, channel);
+		return;
+	}
+
+	wbs = wb->proto_data;
+	silcpurple_wb_parse(wbs, wb, (unsigned char *)message, message_len);
+}
+
+/* Send whiteboard message */
+
+void silcpurple_wb_send(PurpleWhiteboard *wb, GList *draw_list)
+{
+	SilcPurpleWb wbs = wb->proto_data;
+	SilcBuffer packet;
+	GList *list;
+	int len;
+        PurpleConnection *gc;
+        SilcPurple sg;
+
+	g_return_if_fail(draw_list);
+	gc = purple_account_get_connection(wb->account);
+	g_return_if_fail(gc);
+ 	sg = gc->proto_data;
+	g_return_if_fail(sg);
+
+	len = SILCPURPLE_WB_HEADER;
+	for (list = draw_list; list; list = list->next)
+		len += 4;
+
+	packet = silc_buffer_alloc_size(len);
+	if (!packet)
+		return;
+
+	/* Assmeble packet */
+	silc_buffer_format(packet,
+			   SILC_STR_UI32_STRING(SILCPURPLE_WB_MIME),
+			   SILC_STR_UI_CHAR(SILCPURPLE_WB_DRAW),
+			   SILC_STR_UI_SHORT(wbs->width),
+			   SILC_STR_UI_SHORT(wbs->height),
+			   SILC_STR_UI_INT(wbs->brush_color),
+			   SILC_STR_UI_SHORT(wbs->brush_size),
+			   SILC_STR_END);
+	silc_buffer_pull(packet, SILCPURPLE_WB_HEADER);
+	for (list = draw_list; list; list = list->next) {
+		silc_buffer_format(packet,
+				   SILC_STR_UI_INT(GPOINTER_TO_INT(list->data)),
+				   SILC_STR_END);
+		silc_buffer_pull(packet, 4);
+	}
+
+	/* Send the message */
+	if (wbs->type == 0) {
+		/* Private message */
+		silc_client_send_private_message(sg->client, sg->conn, 
+						 wbs->u.client, 
+						 SILC_MESSAGE_FLAG_DATA,
+						 packet->head, len, TRUE);
+	} else if (wbs->type == 1) {
+		/* Channel message. Channel private keys are not supported. */
+		silc_client_send_channel_message(sg->client, sg->conn,
+						 wbs->u.channel, NULL,
+						 SILC_MESSAGE_FLAG_DATA,
+						 packet->head, len, TRUE);
+	}
+
+	silc_buffer_free(packet);
+}
+
+/* Purple Whiteboard operations */
+
+void silcpurple_wb_start(PurpleWhiteboard *wb)
+{
+	/* Nothing here.  Everything is in initialization */
+}
+
+void silcpurple_wb_end(PurpleWhiteboard *wb)
+{
+	silc_free(wb->proto_data);
+	wb->proto_data = NULL;
+}
+
+void silcpurple_wb_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height)
+{
+	SilcPurpleWb wbs = wb->proto_data;
+	*width = wbs->width;
+	*height = wbs->height;
+}
+
+void silcpurple_wb_set_dimensions(PurpleWhiteboard *wb, int width, int height)
+{
+	SilcPurpleWb wbs = wb->proto_data;
+	wbs->width = width > SILCPURPLE_WB_WIDTH_MAX ? SILCPURPLE_WB_WIDTH_MAX :
+			width;
+	wbs->height = height > SILCPURPLE_WB_HEIGHT_MAX ? SILCPURPLE_WB_HEIGHT_MAX :
+			height;
+
+	/* Update whiteboard */
+	purple_whiteboard_set_dimensions(wb, wbs->width, wbs->height);
+}
+
+void silcpurple_wb_get_brush(const PurpleWhiteboard *wb, int *size, int *color)
+{
+	SilcPurpleWb wbs = wb->proto_data;
+	*size = wbs->brush_size;
+	*color = wbs->brush_color;
+}
+
+void silcpurple_wb_set_brush(PurpleWhiteboard *wb, int size, int color)
+{
+	SilcPurpleWb wbs = wb->proto_data;
+	wbs->brush_size = size;
+	wbs->brush_color = color;
+
+	/* Update whiteboard */
+	purple_whiteboard_set_brush(wb, size, color);
+}
+
+void silcpurple_wb_clear(PurpleWhiteboard *wb)
+{
+	SilcPurpleWb wbs = wb->proto_data;
+	SilcBuffer packet;
+	int len;
+        PurpleConnection *gc;
+        SilcPurple sg;
+
+	gc = purple_account_get_connection(wb->account);
+	g_return_if_fail(gc);
+ 	sg = gc->proto_data;
+	g_return_if_fail(sg);
+
+	len = SILCPURPLE_WB_HEADER;
+	packet = silc_buffer_alloc_size(len);
+	if (!packet)
+		return;
+
+	/* Assmeble packet */
+	silc_buffer_format(packet,
+			   SILC_STR_UI32_STRING(SILCPURPLE_WB_MIME),
+			   SILC_STR_UI_CHAR(SILCPURPLE_WB_CLEAR),
+			   SILC_STR_UI_SHORT(wbs->width),
+			   SILC_STR_UI_SHORT(wbs->height),
+			   SILC_STR_UI_INT(wbs->brush_color),
+			   SILC_STR_UI_SHORT(wbs->brush_size),
+			   SILC_STR_END);
+
+	/* Send the message */
+	if (wbs->type == 0) {
+		/* Private message */
+		silc_client_send_private_message(sg->client, sg->conn, 
+						 wbs->u.client, 
+						 SILC_MESSAGE_FLAG_DATA,
+						 packet->head, len, TRUE);
+	} else if (wbs->type == 1) {
+		/* Channel message */
+		silc_client_send_channel_message(sg->client, sg->conn,
+						 wbs->u.channel, NULL,
+						 SILC_MESSAGE_FLAG_DATA,
+						 packet->head, len, TRUE);
+	}
+
+	silc_buffer_free(packet);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpurple/protocols/silc10/wb.h	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,49 @@
+/*
+
+  silcpurple.h
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2005 Pekka Riikonen
+
+  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; version 2 of the License.
+
+  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.
+
+*/
+
+#ifndef SILCPURPLE_WB_H
+#define SILCPURPLE_WB_H
+
+#include "silcpurple.h"
+#include "whiteboard.h"
+
+PurpleWhiteboard *
+silcpurple_wb_init(SilcPurple sg, SilcClientEntry client_entry);
+PurpleWhiteboard *
+silcpurple_wb_init_ch(SilcPurple sg, SilcChannelEntry channel);
+void silcpurple_wb_receive(SilcClient client, SilcClientConnection conn,
+			 SilcClientEntry sender, SilcMessagePayload payload,
+			 SilcMessageFlags flags, const unsigned char *message,
+			 SilcUInt32 message_len);
+void silcpurple_wb_receive_ch(SilcClient client, SilcClientConnection conn,
+			    SilcClientEntry sender, SilcChannelEntry channel,
+			    SilcMessagePayload payload,
+			    SilcMessageFlags flags,
+			    const unsigned char *message,
+			    SilcUInt32 message_len);
+void silcpurple_wb_start(PurpleWhiteboard *wb);
+void silcpurple_wb_end(PurpleWhiteboard *wb);
+void silcpurple_wb_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height);
+void silcpurple_wb_set_dimensions(PurpleWhiteboard *wb, int width, int height);
+void silcpurple_wb_get_brush(const PurpleWhiteboard *wb, int *size, int *color);
+void silcpurple_wb_set_brush(PurpleWhiteboard *wb, int size, int color);
+void silcpurple_wb_send(PurpleWhiteboard *wb, GList *draw_list);
+void silcpurple_wb_clear(PurpleWhiteboard *wb);
+
+#endif /* SILCPURPLE_WB_H */
--- a/libpurple/protocols/simple/simple.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/simple/simple.c	Mon Jun 18 01:48:35 2007 +0000
@@ -1243,7 +1243,7 @@
 					foundxpidf = TRUE;
 				if(tmp2) {
 					*tmp2 = ',';
-					tmp = tmp2;
+					tmp = tmp2 + 1;
 					while(*tmp == ' ') tmp++;
 				} else
 					tmp = 0;
--- a/libpurple/protocols/toc/PROTOCOL	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/toc/PROTOCOL	Mon Jun 18 01:48:35 2007 +0000
@@ -14,10 +14,10 @@
 #   along with this program; if not, write to the Free Software
 #   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
-# Note from Jim Duchek, gaim maintainer -- this may not be the latest
-# version of this document, I provide it as a service.  Download a copy
-# of TiK (http://www.aim.aol.com/tik/) for the latest version of this
-# doc.
+# Note from Jim Duchek, former libpurple maintainer -- this may not be
+# the latest version of this document, I provide it as a service.
+# Download a copy of TiK (http://www.aim.aol.com/tik/) for the latest
+# version of this doc.
 
 # Note from Eric Warmenhoven, random guy -- this appears to be the last
 # published version of the protocol, and AOL has stopped hosting the TiK
--- a/libpurple/protocols/yahoo/yahoo.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/yahoo/yahoo.c	Mon Jun 18 01:48:35 2007 +0000
@@ -2310,7 +2310,7 @@
 			 * are you trying to pull? */
 			guchar *start;
 
-			purple_debug_warning("yahoo", "Error in YMSG stream, got something not a YMSG packet!");
+			purple_debug_warning("yahoo", "Error in YMSG stream, got something not a YMSG packet!\n");
 
 			start = memchr(yd->rxqueue + 1, 'Y', yd->rxlen - 1);
 			if (start) {
@@ -2377,7 +2377,11 @@
 	}
 
 	if (source < 0) {
-		purple_connection_error(gc, _("Unable to connect."));
+		gchar *tmp;
+		tmp = g_strdup_printf(_("Could not establish a connection with the server:\n%s"),
+				error_message);
+		purple_connection_error(gc, tmp);
+		g_free(tmp);
 		return;
 	}
 
@@ -2405,7 +2409,11 @@
 	}
 
 	if (source < 0) {
-		purple_connection_error(gc, _("Unable to connect."));
+		gchar *tmp;
+		tmp = g_strdup_printf(_("Could not establish a connection with the server:\n%s"),
+				error_message);
+		purple_connection_error(gc, tmp);
+		g_free(tmp);
 		return;
 	}
 
@@ -2507,12 +2515,16 @@
 	if (written < 0 && errno == EAGAIN)
 		written = 0;
 	else if (written <= 0) {
+		gchar *tmp;
 		g_free(yd->auth);
 		yd->auth = NULL;
 		if (gc->inpa)
 			purple_input_remove(gc->inpa);
 		gc->inpa = 0;
-		purple_connection_error(gc, _("Unable to connect."));
+		tmp = g_strdup_printf(_("Lost connection with %s:\n%s"),
+				"login.yahoo.com:80", strerror(errno));
+		purple_connection_error(gc, tmp);
+		g_free(tmp);
 		return;
 	}
 
@@ -2533,7 +2545,11 @@
 	PurpleConnection *gc = data;
 
 	if (source < 0) {
-		purple_connection_error(gc, _("Unable to connect."));
+		gchar *tmp;
+		tmp = g_strdup_printf(_("Could not establish a connection with %s:\n%s"),
+				"login.yahoo.com:80", error_message);
+		purple_connection_error(gc, tmp);
+		g_free(tmp);
 		return;
 	}
 
@@ -2616,8 +2632,7 @@
 
 	if (error_message != NULL)
 	{
-		/* TODO: Include error_message in the message below */
-		purple_connection_error(gc, _("Unable to connect."));
+		purple_connection_error(gc, error_message);
 		return;
 	}
 
--- a/libpurple/protocols/yahoo/yahoo_packet.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/yahoo/yahoo_packet.c	Mon Jun 18 01:48:35 2007 +0000
@@ -110,6 +110,29 @@
 	return len;
 }
 
+/*
+ * 'len' is the value given to us by the server that is supposed to
+ * be the length of 'data'.  But apparently there's a time when this
+ * length is incorrect.  Christopher Layne thinks it might be a bug
+ * in their server code.
+ *
+ * The following information is from Christopher:
+ *
+ * It sometimes happens when Yahoo! sends a packet continuation within
+ * chat.  Sometimes when joining a large chatroom the initial
+ * SERVICE_CHATJOIN packet will be so large that it will need to be
+ * split into multiple packets.  That's fine, except that the length
+ * of the second packet is wrong.  The packet has the same length as
+ * the first packet, and the length given in the header is the same,
+ * however the actual data in the packet is shorter than this length.
+ * So half of the packet contains good, valid data, and then the rest
+ * of the packet is junk.  Luckily there is a null terminator after
+ * the valid data and before the invalid data.
+ *
+ * What does all this mean?  It means that we parse through the data
+ * pulling out key/value pairs until we've parsed 'len' bytes, or until
+ * we run into a null terminator, whichever comes first.
+ */
 void yahoo_packet_read(struct yahoo_packet *pkt, const guchar *data, int len)
 {
 	int pos = 0;
@@ -121,18 +144,8 @@
 
 	while (pos + 1 < len)
 	{
-		/* this is weird, and in one of the chat packets, and causes us to
-		 * think all the values are keys and all the keys are values after
-		 * this point if we don't handle it */
-		if (data[pos] == '\0') {
-			while (pos + 1 < len) {
-				if (data[pos] == 0xc0 && data[pos + 1] == 0x80)
-					break;
-				pos++;
-			}
-			pos += 2;
-			continue;
-		}
+		if (data[pos] == '\0')
+			break;
 
 		pair = g_new0(struct yahoo_pair, 1);
 
--- a/libpurple/protocols/zephyr/zephyr.h	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/protocols/zephyr/zephyr.h	Mon Jun 18 01:48:35 2007 +0000
@@ -109,7 +109,7 @@
     ZChecksum_t		z_checksum;
     int			z_num_other_fields;
     char		*z_other_fields[Z_MAXOTHERFIELDS];
-    void		*z_message;
+    caddr_t		z_message;
     int			z_message_len;
 } ZNotice_t;
 
--- a/libpurple/proxy.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/proxy.c	Mon Jun 18 01:48:35 2007 +0000
@@ -559,7 +559,7 @@
 	int len, headers_len, status = 0;
 	gboolean error;
 	PurpleProxyConnectData *connect_data = data;
-	guchar *p;
+	char *p;
 	gsize max_read;
 
 	if (connect_data->read_buffer == NULL)
@@ -569,7 +569,7 @@
 		connect_data->read_len = 0;
 	}
 
-	p = connect_data->read_buffer + connect_data->read_len;
+	p = (char *)connect_data->read_buffer + connect_data->read_len;
 	max_read = connect_data->read_buf_len - connect_data->read_len - 1;
 
 	len = read(connect_data->fd, p, max_read);
@@ -596,11 +596,11 @@
 	connect_data->read_len += len;
 	p[len] = '\0';
 
-	p = (guchar *)g_strstr_len((const gchar *)connect_data->read_buffer,
+	p = g_strstr_len((const gchar *)connect_data->read_buffer,
 			connect_data->read_len, "\r\n\r\n");
 	if (p != NULL) {
 		*p = '\0';
-		headers_len = (p - connect_data->read_buffer) + 4;
+		headers_len = (p - (char *)connect_data->read_buffer) + 4;
 	} else if(len == max_read)
 		headers_len = len;
 	else
@@ -610,34 +610,34 @@
 	if (!error)
 	{
 		int major;
-		p = connect_data->read_buffer + 5;
-		major = strtol((const char *)p, (char**)&p, 10);
+		p = (char *)connect_data->read_buffer + 5;
+		major = strtol(p, &p, 10);
 		error = (major == 0) || (*p != '.');
 		if(!error) {
 			int minor;
 			p++;
-			minor = strtol((const char *)p, (char **)&p, 10);
+			minor = strtol(p, &p, 10);
 			error = (*p != ' ');
 			if(!error) {
 				p++;
-				status = strtol((const char *)p, (char **)&p, 10);
+				status = strtol(p, &p, 10);
 				error = (*p != ' ');
 			}
 		}
 	}
 
 	/* Read the contents */
-	p = (guchar *)g_strrstr((const gchar *)connect_data->read_buffer, "Content-Length: ");
+	p = g_strrstr((const gchar *)connect_data->read_buffer, "Content-Length: ");
 	if (p != NULL)
 	{
 		gchar *tmp;
 		int len = 0;
 		char tmpc;
 		p += strlen("Content-Length: ");
-		tmp = strchr((const char *)p, '\r');
+		tmp = strchr(p, '\r');
 		if(tmp)
 			*tmp = '\0';
-		len = atoi((const char *)p);
+		len = atoi(p);
 		if(tmp)
 			*tmp = '\r';
 
@@ -1059,6 +1059,22 @@
 	}
 }
 
+static gboolean
+s5_ensure_buffer_length(PurpleProxyConnectData *connect_data, int len)
+{
+	if(connect_data->read_len < len) {
+		if(connect_data->read_buf_len < len) {
+			/* it's not just that we haven't read enough, it's that we haven't tried to read enough yet */
+			purple_debug_info("s5", "reallocing from %d to %d\n", connect_data->read_buf_len, len);
+			connect_data->read_buf_len = len;
+			connect_data->read_buffer = g_realloc(connect_data->read_buffer, connect_data->read_buf_len);
+		}
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
 static void
 s5_canread_again(gpointer data, gint source, PurpleInputCondition cond)
 {
@@ -1067,7 +1083,7 @@
 	int len;
 
 	if (connect_data->read_buffer == NULL) {
-		connect_data->read_buf_len = 512;
+		connect_data->read_buf_len = 4;
 		connect_data->read_buffer = g_malloc(connect_data->read_buf_len);
 		connect_data->read_len = 0;
 	}
@@ -1075,8 +1091,6 @@
 	dest = connect_data->read_buffer + connect_data->read_len;
 	buf = connect_data->read_buffer;
 
-	purple_debug_info("socks5 proxy", "Able to read again.\n");
-
 	len = read(connect_data->fd, dest, (connect_data->read_buf_len - connect_data->read_len));
 
 	if (len == 0)
@@ -1119,33 +1133,31 @@
 	/* Skip past BND.ADDR */
 	switch(buf[3]) {
 		case 0x01: /* the address is a version-4 IP address, with a length of 4 octets */
-			if(connect_data->read_len < 4 + 4)
+			if(!s5_ensure_buffer_length(connect_data, 4 + 4))
 				return;
 			buf += 4 + 4;
 			break;
 		case 0x03: /* the address field contains a fully-qualified domain name.  The first
 					  octet of the address field contains the number of octets of name that
 					  follow, there is no terminating NUL octet. */
-			if(connect_data->read_len < 4 + 1)
+			if(!s5_ensure_buffer_length(connect_data, 4 + 1))
 				return;
-			buf += 4 + 1;
-			if(connect_data->read_len < 4 + 1 + buf[0])
+			buf += 4;
+			if(!s5_ensure_buffer_length(connect_data, 4 + 1 + buf[0]))
 				return;
-			buf += buf[0];
+			buf += buf[0] + 1;
 			break;
 		case 0x04: /* the address is a version-6 IP address, with a length of 16 octets */
-			if(connect_data->read_len < 4 + 16)
+			if(!s5_ensure_buffer_length(connect_data, 4 + 16))
 				return;
 			buf += 4 + 16;
 			break;
 	}
 
-	if(connect_data->read_len < (buf - connect_data->read_buffer) + 2)
+	/* Skip past BND.PORT */
+	if(!s5_ensure_buffer_length(connect_data, (buf - connect_data->read_buffer) + 2))
 		return;
 
-	/* Skip past BND.PORT */
-	buf += 2;
-
 	purple_proxy_connect_data_connected(connect_data);
 }
 
--- a/libpurple/prpl.h	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/prpl.h	Mon Jun 18 01:48:35 2007 +0000
@@ -54,7 +54,9 @@
  */
 #define NO_BUDDY_ICONS {NULL, 0, 0, 0, 0, 0, 0}
 
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
 
 #include "blist.h"
 #include "conversation.h"
--- a/libpurple/purple-client.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/purple-client.c	Mon Jun 18 01:48:35 2007 +0000
@@ -5,7 +5,7 @@
 #include <stdlib.h>
 
 #include "dbus-purple.h"
-#include "purple-client-bindings.h"
+#include "purple-client.h"
 
 static DBusGConnection *bus;
 static DBusGProxy *purple_proxy;
--- a/libpurple/purple-remote	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/purple-remote	Mon Jun 18 01:48:35 2007 +0000
@@ -31,7 +31,7 @@
         return result
             
 def show_help():
-    print """This program uses DBus to communicate with purple.
+    print """This program uses D-Bus to communicate with purple.
 
 Usage:
 
@@ -94,10 +94,8 @@
 def execute(uri):
     match = re.match(urlregexp, uri)
     protocol = match.group(2)
-    if protocol == "xmpp"
+    if protocol == "xmpp":
         protocol = "jabber"
-    if protocol == "aim" or protocol == "icq":
-        protocol = "oscar"
     if protocol is not None:
         protocol = "prpl-" + protocol
     command = match.group(5)
--- a/libpurple/sslconn.h	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/sslconn.h	Mon Jun 18 01:48:35 2007 +0000
@@ -170,6 +170,7 @@
 
 /**
  * Adds an input watcher for the specified SSL connection.
+ * Once the SSL handshake is complete, use this to watch for actual data across it.
  *
  * @param gsc   The SSL connection handle.
  * @param func  The callback function.
--- a/libpurple/status.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/status.c	Mon Jun 18 01:48:35 2007 +0000
@@ -1275,6 +1275,7 @@
 purple_presence_set_idle(PurplePresence *presence, gboolean idle, time_t idle_time)
 {
 	gboolean old_idle;
+	time_t current_time;
 
 	g_return_if_fail(presence != NULL);
 
@@ -1285,14 +1286,14 @@
 	presence->idle      = idle;
 	presence->idle_time = (idle ? idle_time : 0);
 
+	current_time = time(NULL);
+
 	if (purple_presence_get_context(presence) == PURPLE_PRESENCE_CONTEXT_BUDDY)
 	{
-		time_t current_time = time(NULL);
-
 		update_buddy_idle(purple_presence_get_buddy(presence), presence, current_time,
-		old_idle, idle);
+		                  old_idle, idle);
 	}
-	else if(purple_presence_get_context(presence) == PURPLE_PRESENCE_CONTEXT_ACCOUNT)
+	else if (purple_presence_get_context(presence) == PURPLE_PRESENCE_CONTEXT_ACCOUNT)
 	{
 		PurpleAccount *account;
 		PurpleConnection *gc;
@@ -1312,9 +1313,10 @@
 					msg = g_strdup_printf(_("+++ %s became idle"), purple_account_get_username(account));
 				else
 					msg = g_strdup_printf(_("+++ %s became unidle"), purple_account_get_username(account));
+
 				purple_log_write(log, PURPLE_MESSAGE_SYSTEM,
-							   purple_account_get_username(account),
-							   idle_time, msg);
+				                 purple_account_get_username(account),
+				                 (idle ? idle_time : current_time), msg);
 				g_free(msg);
 			}
 		}
@@ -1326,7 +1328,7 @@
 			prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
 
 		if (prpl_info && prpl_info->set_idle)
-			prpl_info->set_idle(gc, (idle ? (time(NULL) - idle_time) : 0));
+			prpl_info->set_idle(gc, (idle ? (current_time - idle_time) : 0));
 	}
 }
 
--- a/libpurple/util.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/util.c	Mon Jun 18 01:48:35 2007 +0000
@@ -46,6 +46,7 @@
 	} website;
 
 	char *url;
+	int num_times_redirected;
 	gboolean full;
 	char *user_agent;
 	gboolean http11;
@@ -1259,14 +1260,17 @@
 								pt->dest_tag = y; \
 								tags = g_list_prepend(tags, pt); \
 							} \
-							xhtml = g_string_append(xhtml, "<" y); \
-							c += strlen("<" x ); \
-							xhtml = g_string_append(xhtml, innards->str); \
-							xhtml = g_string_append_c(xhtml, '>'); \
+							if(xhtml) { \
+								xhtml = g_string_append(xhtml, "<" y); \
+								xhtml = g_string_append(xhtml, innards->str); \
+								xhtml = g_string_append_c(xhtml, '>'); \
+							} \
 							c = p + 1; \
 						} else { \
-							xhtml = g_string_append(xhtml, "&lt;"); \
-							plain = g_string_append_c(plain, '<'); \
+							if(xhtml) \
+								xhtml = g_string_append(xhtml, "&lt;"); \
+							if(plain) \
+								plain = g_string_append_c(plain, '<'); \
 							c++; \
 						} \
 						g_string_free(innards, TRUE); \
@@ -1275,16 +1279,19 @@
 						if(!g_ascii_strncasecmp(c, "<" x, strlen("<" x)) && \
 								(*(c+strlen("<" x)) == '>' || \
 								 !g_ascii_strncasecmp(c+strlen("<" x), "/>", 2))) { \
-							xhtml = g_string_append(xhtml, "<" y); \
+							if(xhtml) \
+								xhtml = g_string_append(xhtml, "<" y); \
 							c += strlen("<" x); \
 							if(*c != '/') { \
 								struct purple_parse_tag *pt = g_new0(struct purple_parse_tag, 1); \
 								pt->src_tag = x; \
 								pt->dest_tag = y; \
 								tags = g_list_prepend(tags, pt); \
-								xhtml = g_string_append_c(xhtml, '>'); \
+								if(xhtml) \
+									xhtml = g_string_append_c(xhtml, '>'); \
 							} else { \
-								xhtml = g_string_append(xhtml, "/>");\
+								if(xhtml) \
+									xhtml = g_string_append(xhtml, "/>");\
 							} \
 							c = strchr(c, '>') + 1; \
 							continue; \
@@ -1294,11 +1301,18 @@
 purple_markup_html_to_xhtml(const char *html, char **xhtml_out,
 						  char **plain_out)
 {
-	GString *xhtml = g_string_new("");
-	GString *plain = g_string_new("");
+	GString *xhtml = NULL;
+	GString *plain = NULL;
 	GList *tags = NULL, *tag;
 	const char *c = html;
 
+	g_return_if_fail(xhtml_out != NULL || plain_out != NULL);
+
+	if(xhtml_out)
+		xhtml = g_string_new("");
+	if(plain_out)
+		plain = g_string_new("");
+
 	while(c && *c) {
 		if(*c == '<') {
 			if(*(c+1) == '/') { /* closing tag */
@@ -1314,7 +1328,8 @@
 				if(tag) {
 					while(tags) {
 						struct purple_parse_tag *pt = tags->data;
-						g_string_append_printf(xhtml, "</%s>", pt->dest_tag);
+						if(xhtml)
+							g_string_append_printf(xhtml, "</%s>", pt->dest_tag);
 						if(tags == tag)
 							break;
 						tags = g_list_remove(tags, pt);
@@ -1332,8 +1347,10 @@
 					if(*end == '>') {
 						c = end+1;
 					} else {
-						xhtml = g_string_append(xhtml, "&lt;");
-						plain = g_string_append_c(plain, '<');
+						if(xhtml)
+							xhtml = g_string_append(xhtml, "&lt;");
+						if(plain)
+							plain = g_string_append_c(plain, '<');
 						c++;
 					}
 				}
@@ -1362,7 +1379,8 @@
 				ALLOW_TAG("span");
 				ALLOW_TAG("strong");
 				ALLOW_TAG("ul");
-
+				ALLOW_TAG("img");
+				
 				/* we skip <HR> because it's not legal in XHTML-IM.  However,
 				 * we still want to send something sensible, so we put a
 				 * linebreak in its place. <BR> also needs special handling
@@ -1373,8 +1391,9 @@
 							!g_ascii_strncasecmp(c+3, "/>", 2) ||
 							!g_ascii_strncasecmp(c+3, " />", 3))) {
 					c = strchr(c, '>') + 1;
-					xhtml = g_string_append(xhtml, "<br/>");
-					if(*c != '\n')
+					if(xhtml)
+						xhtml = g_string_append(xhtml, "<br/>");
+					if(plain && *c != '\n')
 						plain = g_string_append_c(plain, '\n');
 					continue;
 				}
@@ -1384,7 +1403,8 @@
 					pt->dest_tag = "span";
 					tags = g_list_prepend(tags, pt);
 					c = strchr(c, '>') + 1;
-					xhtml = g_string_append(xhtml, "<span style='font-weight: bold;'>");
+					if(xhtml)
+						xhtml = g_string_append(xhtml, "<span style='font-weight: bold;'>");
 					continue;
 				}
 				if(!g_ascii_strncasecmp(c, "<u>", 3) || !g_ascii_strncasecmp(c, "<underline>", strlen("<underline>"))) {
@@ -1393,7 +1413,8 @@
 					pt->dest_tag = "span";
 					tags = g_list_prepend(tags, pt);
 					c = strchr(c, '>') + 1;
-					xhtml = g_string_append(xhtml, "<span style='text-decoration: underline;'>");
+					if (xhtml)
+						xhtml = g_string_append(xhtml, "<span style='text-decoration: underline;'>");
 					continue;
 				}
 				if(!g_ascii_strncasecmp(c, "<s>", 3) || !g_ascii_strncasecmp(c, "<strike>", strlen("<strike>"))) {
@@ -1402,7 +1423,8 @@
 					pt->dest_tag = "span";
 					tags = g_list_prepend(tags, pt);
 					c = strchr(c, '>') + 1;
-					xhtml = g_string_append(xhtml, "<span style='text-decoration: line-through;'>");
+					if(xhtml)
+						xhtml = g_string_append(xhtml, "<span style='text-decoration: line-through;'>");
 					continue;
 				}
 				if(!g_ascii_strncasecmp(c, "<sub>", 5)) {
@@ -1411,7 +1433,8 @@
 					pt->dest_tag = "span";
 					tags = g_list_prepend(tags, pt);
 					c = strchr(c, '>') + 1;
-					xhtml = g_string_append(xhtml, "<span style='vertical-align:sub;'>");
+					if(xhtml)
+						xhtml = g_string_append(xhtml, "<span style='vertical-align:sub;'>");
 					continue;
 				}
 				if(!g_ascii_strncasecmp(c, "<sup>", 5)) {
@@ -1420,7 +1443,8 @@
 					pt->dest_tag = "span";
 					tags = g_list_prepend(tags, pt);
 					c = strchr(c, '>') + 1;
-					xhtml = g_string_append(xhtml, "<span style='vertical-align:super;'>");
+					if(xhtml)
+						xhtml = g_string_append(xhtml, "<span style='vertical-align:super;'>");
 					continue;
 				}
 				if(!g_ascii_strncasecmp(c, "<font", 5) && (*(c+5) == '>' || *(c+5) == ' ')) {
@@ -1514,7 +1538,10 @@
 					pt->dest_tag = "span";
 					tags = g_list_prepend(tags, pt);
 					if(style->len)
-						g_string_append_printf(xhtml, "<span style='%s'>", g_strstrip(style->str));
+					{
+						if(xhtml)
+							g_string_append_printf(xhtml, "<span style='%s'>", g_strstrip(style->str));
+					}
 					else
 						pt->ignore = TRUE;
 					g_string_free(style, TRUE);
@@ -1534,7 +1561,8 @@
 								color = g_string_append_c(color, *q);
 								q++;
 							}
-							g_string_append_printf(xhtml, "<span style='background: %s;'>", g_strstrip(color->str));
+							if(xhtml)
+								g_string_append_printf(xhtml, "<span style='background: %s;'>", g_strstrip(color->str));
 							g_string_free(color, TRUE);
 							if ((c = strchr(c, '>')) != NULL)
 								c++;
@@ -1555,14 +1583,17 @@
 				if(!g_ascii_strncasecmp(c, "<!--", strlen("<!--"))) {
 					char *p = strstr(c + strlen("<!--"), "-->");
 					if(p) {
-						xhtml = g_string_append(xhtml, "<!--");
+						if(xhtml)
+							xhtml = g_string_append(xhtml, "<!--");
 						c += strlen("<!--");
 						continue;
 					}
 				}
 
-				xhtml = g_string_append(xhtml, "&lt;");
-				plain = g_string_append_c(plain, '<');
+				if(xhtml)
+					xhtml = g_string_append(xhtml, "&lt;");
+				if(plain)
+					plain = g_string_append_c(plain, '<');
 				c++;
 			}
 		} else if(*c == '&') {
@@ -1575,29 +1606,31 @@
 				g_snprintf(buf, sizeof(buf), "%c", *c);
 				pln = buf;
 			}
-			xhtml = g_string_append_len(xhtml, c, len);
-			plain = g_string_append(plain, pln);
+			if(xhtml)
+				xhtml = g_string_append_len(xhtml, c, len);
+			if(plain)
+				plain = g_string_append(plain, pln);
 			c += len;
 		} else {
-			xhtml = g_string_append_c(xhtml, *c);
-			plain = g_string_append_c(plain, *c);
+			if(xhtml)
+				xhtml = g_string_append_c(xhtml, *c);
+			if(plain)
+				plain = g_string_append_c(plain, *c);
 			c++;
 		}
 	}
-	tag = tags;
-	while(tag) {
-		struct purple_parse_tag *pt = tag->data;
-		if(!pt->ignore)
-			g_string_append_printf(xhtml, "</%s>", pt->dest_tag);
-		tag = tag->next;
+	if(xhtml) {
+		for (tag = tags; tag ; tag = tag->next) {
+			struct purple_parse_tag *pt = tag->data;
+			if(!pt->ignore)
+				g_string_append_printf(xhtml, "</%s>", pt->dest_tag);
+		}
 	}
 	g_list_free(tags);
 	if(xhtml_out)
-		*xhtml_out = g_strdup(xhtml->str);
+		*xhtml_out = g_string_free(xhtml, FALSE);
 	if(plain_out)
-		*plain_out = g_strdup(plain->str);
-	g_string_free(xhtml, TRUE);
-	g_string_free(plain, TRUE);
+		*plain_out = g_string_free(plain, FALSE);
 }
 
 /* The following are probably reasonable changes:
@@ -2621,14 +2654,17 @@
 
 	if (len >= 4)
 	{
-		if (!strncmp((char *)data, "BM", 2))
-			return "bmp";
-		else if (!strncmp((char *)data, "GIF8", 4))
+		if (!strncmp((char *)data, "GIF8", 4))
 			return "gif";
-		else if (!strncmp((char *)data, "\xff\xd8\xff\xe0", 4))
+		else if (!strncmp((char *)data, "\xff\xd8\xff", 3)) /* 4th may be e0 through ef */
 			return "jpg";
 		else if (!strncmp((char *)data, "\x89PNG", 4))
 			return "png";
+		else if (!strncmp((char *)data, "MM", 2) ||
+				 !strncmp((char *)data, "II", 2))
+			return "tif";
+		else if (!strncmp((char *)data, "BM", 2))
+			return "bmp";
 	}
 
 	return "icon";
@@ -3186,6 +3222,17 @@
 		g_hash_table_destroy(params);
 }
 
+/*
+ * TODO: Should probably add a "gboolean *ret_ishttps" parameter that
+ *       is set to TRUE if this URL is https, otherwise it is set to
+ *       FALSE.  But that change will break the API.
+ *
+ *       This is important for Yahoo! web messenger login.  They now
+ *       force https login, and if you access the web messenger login
+ *       page via http then it redirects you to the https version, but
+ *       purple_util_fetch_url() ignores the "https" and attempts to
+ *       fetch the URL via http again, which gets redirected again.
+ */
 gboolean
 purple_url_parse(const char *url, char **ret_host, int *ret_port,
 			   char **ret_path, char **ret_user, char **ret_passwd)
@@ -3206,12 +3253,16 @@
 
 	g_return_val_if_fail(url != NULL, FALSE);
 
-	if ((turl = strstr(url, "http://")) != NULL ||
-		(turl = strstr(url, "HTTP://")) != NULL)
+	if ((turl = purple_strcasestr(url, "http://")) != NULL)
 	{
 		turl += 7;
 		url = turl;
 	}
+	else if ((turl = purple_strcasestr(url, "https://")) != NULL)
+	{
+		turl += 8;
+		url = turl;
+	}
 
 	/* parse out authentication information if supplied */
 	/* Only care about @ char BEFORE the first / */
@@ -3291,85 +3342,92 @@
 			   PurpleUtilFetchUrlData *gfud)
 {
 	gchar *s;
-
-	if ((s = g_strstr_len(data, data_len, "Location: ")) != NULL)
+	gchar *new_url, *temp_url, *end;
+	gboolean full;
+	int len;
+
+	if ((s = g_strstr_len(data, data_len, "Location: ")) == NULL)
+		/* We're not being redirected */
+		return FALSE;
+
+	s += strlen("Location: ");
+	end = strchr(s, '\r');
+
+	/* Just in case :) */
+	if (end == NULL)
+		end = strchr(s, '\n');
+
+	if (end == NULL)
+		return FALSE;
+
+	len = end - s;
+
+	new_url = g_malloc(len + 1);
+	strncpy(new_url, s, len);
+	new_url[len] = '\0';
+
+	full = gfud->full;
+
+	if (*new_url == '/' || g_strstr_len(new_url, len, "://") == NULL)
 	{
-		gchar *new_url, *temp_url, *end;
-		gboolean full;
-		int len;
-
-		s += strlen("Location: ");
-		end = strchr(s, '\r');
-
-		/* Just in case :) */
-		if (end == NULL)
-			end = strchr(s, '\n');
-
-		if (end == NULL)
-			return FALSE;
-
-		len = end - s;
-
-		new_url = g_malloc(len + 1);
-		strncpy(new_url, s, len);
-		new_url[len] = '\0';
-
-		full = gfud->full;
-
-		if (*new_url == '/' || g_strstr_len(new_url, len, "://") == NULL)
-		{
-			temp_url = new_url;
-
-			new_url = g_strdup_printf("%s:%d%s", gfud->website.address,
-									  gfud->website.port, temp_url);
-
-			g_free(temp_url);
-
-			full = FALSE;
-		}
-
-		purple_debug_info("util", "Redirecting to %s\n", new_url);
-
-		/*
-		 * Try again, with this new location.  This code is somewhat
-		 * ugly, but we need to reuse the gfud because whoever called
-		 * us is holding a reference to it.
-		 */
-		g_free(gfud->url);
-		gfud->url = new_url;
-		gfud->full = full;
-		g_free(gfud->request);
-		gfud->request = NULL;
-
-		purple_input_remove(gfud->inpa);
-		gfud->inpa = 0;
-		close(gfud->fd);
-		gfud->fd = -1;
-		gfud->request_written = 0;
-		gfud->len = 0;
-		gfud->data_len = 0;
-
-		g_free(gfud->website.user);
-		g_free(gfud->website.passwd);
-		g_free(gfud->website.address);
-		g_free(gfud->website.page);
-		purple_url_parse(new_url, &gfud->website.address, &gfud->website.port,
-					   &gfud->website.page, &gfud->website.user, &gfud->website.passwd);
-
-		gfud->connect_data = purple_proxy_connect(NULL, NULL,
-				gfud->website.address, gfud->website.port,
-				url_fetch_connect_cb, gfud);
-
-		if (gfud->connect_data == NULL)
-		{
-			purple_util_fetch_url_error(gfud, _("Unable to connect to %s"),
-					gfud->website.address);
-		}
-
+		temp_url = new_url;
+
+		new_url = g_strdup_printf("%s:%d%s", gfud->website.address,
+								  gfud->website.port, temp_url);
+
+		g_free(temp_url);
+
+		full = FALSE;
+	}
+
+	purple_debug_info("util", "Redirecting to %s\n", new_url);
+
+	gfud->num_times_redirected++;
+	if (gfud->num_times_redirected >= 5)
+	{
+		purple_util_fetch_url_error(gfud,
+				_("Could not open %s: Redirected too many times"),
+				gfud->url);
 		return TRUE;
 	}
 
-	return FALSE;
+	/*
+	 * Try again, with this new location.  This code is somewhat
+	 * ugly, but we need to reuse the gfud because whoever called
+	 * us is holding a reference to it.
+	 */
+	g_free(gfud->url);
+	gfud->url = new_url;
+	gfud->full = full;
+	g_free(gfud->request);
+	gfud->request = NULL;
+
+	purple_input_remove(gfud->inpa);
+	gfud->inpa = 0;
+	close(gfud->fd);
+	gfud->fd = -1;
+	gfud->request_written = 0;
+	gfud->len = 0;
+	gfud->data_len = 0;
+
+	g_free(gfud->website.user);
+	g_free(gfud->website.passwd);
+	g_free(gfud->website.address);
+	g_free(gfud->website.page);
+	purple_url_parse(new_url, &gfud->website.address, &gfud->website.port,
+				   &gfud->website.page, &gfud->website.user, &gfud->website.passwd);
+
+	gfud->connect_data = purple_proxy_connect(NULL, NULL,
+			gfud->website.address, gfud->website.port,
+			url_fetch_connect_cb, gfud);
+
+	if (gfud->connect_data == NULL)
+	{
+		purple_util_fetch_url_error(gfud, _("Unable to connect to %s"),
+				gfud->website.address);
+	}
+
+	return TRUE;
 }
 
 static size_t
--- a/libpurple/win32/global.mak	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/win32/global.mak	Mon Jun 18 01:48:35 2007 +0000
@@ -14,7 +14,7 @@
 GTKSPELL_TOP ?= $(WIN32_DEV_TOP)/gtkspell-2.0.6
 GTK_TOP ?= $(WIN32_DEV_TOP)/gtk_2_0
 GTK_BIN ?= $(GTK_TOP)/bin
-HOWL_TOP ?= $(WIN32_DEV_TOP)/howl-1.0.0
+BONJOUR_TOP ?= $(WIN32_DEV_TOP)/Bonjour_SDK
 LIBXML2_TOP ?= $(WIN32_DEV_TOP)/libxml2
 MEANWHILE_TOP ?= $(WIN32_DEV_TOP)/meanwhile-1.0.2
 NSPR_TOP ?= $(WIN32_DEV_TOP)/nspr-4.6.4
--- a/libpurple/win32/libc_interface.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/win32/libc_interface.c	Mon Jun 18 01:48:35 2007 +0000
@@ -1,6 +1,6 @@
 /*
  * purple
- * 
+ *
  * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -74,7 +74,7 @@
 	int ret;
 
 	ret = connect( socket, addr, length );
-	
+
 	if( ret == SOCKET_ERROR ) {
 		errno = WSAGetLastError();
 		if( errno == WSAEWOULDBLOCK )
@@ -129,6 +129,8 @@
 	if ((ret = sendto(socket, buf, len, flags, to, tolen)
 			) == SOCKET_ERROR) {
 		errno = WSAGetLastError();
+		if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS)
+			errno = EAGAIN;
 		return -1;
 	}
 	return ret;
@@ -302,7 +304,7 @@
 	if(wpurple_is_socket(fd)) {
 		if((ret = recv(fd, buf, size, 0)) == SOCKET_ERROR) {
 			errno = WSAGetLastError();
-			if(errno == WSAEWOULDBLOCK)
+			if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS)
 				errno = EAGAIN;
 			return -1;
 		}
@@ -330,7 +332,7 @@
 
 	if (ret == SOCKET_ERROR) {
 		errno = WSAGetLastError();
-		if(errno == WSAEWOULDBLOCK)
+		if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS)
 			errno = EAGAIN;
 		return -1;
 	}
@@ -350,7 +352,7 @@
 
 	if((ret = recv(fd, buf, len, flags)) == SOCKET_ERROR) {
 			errno = WSAGetLastError();
-			if(errno == WSAEWOULDBLOCK)
+			if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS)
 				errno = EAGAIN;
 			return -1;
 	} else {
@@ -392,7 +394,7 @@
 		z->tz_minuteswest = _timezone/60;
 		z->tz_dsttime = _daylight;
 	}
-	
+
 	if (p != 0) {
 		_ftime(&timebuffer);
 	   	p->tv_sec = timebuffer.time;			/* seconds since 1-1-1970 */
@@ -1044,7 +1046,7 @@
  * Returns: zero if the pathname refers to an existing file system
  * object that has all the tested permissions, or -1 otherwise or on
  * error.
- * 
+ *
  * Since: 2.8
  */
 int
@@ -1056,7 +1058,7 @@
       wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
       int retval;
       int save_errno;
-      
+
       if (wfilename == NULL)
 	{
 	  errno = EINVAL;
@@ -1072,7 +1074,7 @@
       return retval;
     }
   else
-    {    
+    {
       gchar *cp_filename = g_locale_from_utf8 (filename, -1, NULL, NULL, NULL);
       int retval;
       int save_errno;
--- a/libpurple/xmlnode.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/libpurple/xmlnode.c	Mon Jun 18 01:48:35 2007 +0000
@@ -519,38 +519,38 @@
 }
 
 static xmlSAXHandler xmlnode_parser_libxml = {
-	.internalSubset         = NULL,
-	.isStandalone           = NULL,
-	.hasInternalSubset      = NULL,
-	.hasExternalSubset      = NULL,
-	.resolveEntity          = NULL,
-	.getEntity              = NULL,
-	.entityDecl             = NULL,
-	.notationDecl           = NULL,
-	.attributeDecl          = NULL,
-	.elementDecl            = NULL,
-	.unparsedEntityDecl     = NULL,
-	.setDocumentLocator     = NULL,
-	.startDocument          = NULL,
-	.endDocument            = NULL,
-	.startElement           = NULL,
-	.endElement             = NULL,
-	.reference              = NULL,
-	.characters             = xmlnode_parser_element_text_libxml,
-	.ignorableWhitespace    = NULL,
-	.processingInstruction  = NULL,
-	.comment                = NULL,
-	.warning                = NULL,
-	.error                  = xmlnode_parser_error_libxml,
-	.fatalError             = NULL,
-	.getParameterEntity     = NULL,
-	.cdataBlock             = NULL,
-	.externalSubset         = NULL,
-	.initialized            = XML_SAX2_MAGIC,
-	._private               = NULL,
-	.startElementNs         = xmlnode_parser_element_start_libxml,
-	.endElementNs           = xmlnode_parser_element_end_libxml,
-	.serror                 = NULL
+	NULL, /* internalSubset */
+	NULL, /* isStandalone */
+	NULL, /* hasInternalSubset */
+	NULL, /* hasExternalSubset */
+	NULL, /* resolveEntity */
+	NULL, /* getEntity */
+	NULL, /* entityDecl */
+	NULL, /* notationDecl */
+	NULL, /* attributeDecl */
+	NULL, /* elementDecl */
+	NULL, /* unparsedEntityDecl */
+	NULL, /* setDocumentLocator */
+	NULL, /* startDocument */
+	NULL, /* endDocument */
+	NULL, /* startElement */
+	NULL, /* endElement */
+	NULL, /* reference */
+	xmlnode_parser_element_text_libxml, /* characters */
+	NULL, /* ignorableWhitespace */
+	NULL, /* processingInstruction */
+	NULL, /* comment */
+	NULL, /* warning */
+	xmlnode_parser_error_libxml, /* error */
+	NULL, /* fatalError */
+	NULL, /* getParameterEntity */
+	NULL, /* cdataBlock */
+	NULL, /* externalSubset */
+	XML_SAX2_MAGIC, /* initialized */
+	NULL, /* _private */
+	xmlnode_parser_element_start_libxml, /* startElementNs */
+	xmlnode_parser_element_end_libxml,   /* endElementNs   */
+	NULL, /* serror */
 };
 
 xmlnode *
--- a/pidgin.spec.in	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin.spec.in	Mon Jun 18 01:48:35 2007 +0000
@@ -83,6 +83,7 @@
 Summary:    Development headers, documentation, and libraries for Pidgin
 Group:      Applications/Internet
 Requires:   pidgin = %{version}, libpurple-devel = %{version}
+Requires:   gtk2-devel
 Requires:   pkgconfig
 Obsoletes:  gaim-devel
 Provides:   gaim-devel
@@ -95,12 +96,19 @@
 Obsoletes:  gaim-gadugadu
 Obsoletes:  pidgin-tcl < 2.0.0
 Obsoletes:  pidgin-silc < 2.0.0
+%{?_with_sasl:Requires:   cyrus-sasl-plain, cyrus-sasl-md5}
 
 %package -n libpurple-devel
 Summary:    Development headers, documentation, and libraries for libpurple
 Group:      Applications/Internet
 Requires:   libpurple = %{version}
 Requires:   pkgconfig
+%if "%{_vendor}" == "suse"
+# For SuSE:
+%{?_with_dbus:Requires: dbus-1-devel >= 0.35}
+%else
+%{?_with_dbus:Requires: dbus-devel >= 0.35}
+%endif
 
 %if 0%{?_with_howl:1} || 0%{?_with_avahi:1}
 %package -n libpurple-bonjour
@@ -133,6 +141,7 @@
 Summary:    Headers etc. for finch stuffs
 Group:      Applications/Internet
 Requires:   finch = %{version}, libpurple-devel = %{version}
+Requires:   ncurses-devel
 Requires:   pkgconfig
 %endif
 
@@ -449,6 +458,13 @@
 %endif
 
 %changelog
+* Tue Jun 5 2007 Stu Tomlinson <stu@nosnilmot.com>
+- Add missing Requires for gtk2-devel, dbus-devel & ncurses-devel to
+  appropriate -devel subpackages
+
+* Sun May 27 2007 Stu Tomlinson <stu@nosnilmot.com>
+- add cyrus-sasl-plain & cyrus-sasl-md5 to Requires
+
 * Thu May 24 2007 Stu Tomlinson <stu@nosnilmot.com>
 - Silence errors from gtk-update-icon-cache
 - Change Mandriva build dependencies to reflect the correct (lower case)
--- a/pidgin/Makefile.am	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/Makefile.am	Mon Jun 18 01:48:35 2007 +0000
@@ -193,6 +193,7 @@
 	-DLIBDIR=\"$(libdir)/pidgin/\" \
 	-DLOCALEDIR=\"$(datadir)/locale\" \
 	-DSYSCONFDIR=\"$(sysconfdir)\" \
+	-I$(top_builddir)/libpurple \
 	-I$(top_srcdir)/libpurple/ \
 	$(GLIB_CFLAGS) \
 	$(GSTREAMER_CFLAGS) \
--- a/pidgin/Makefile.mingw	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/Makefile.mingw	Mon Jun 18 01:48:35 2007 +0000
@@ -106,26 +106,22 @@
 ##
 ## LIBRARIES
 ##
-LIBPURPLES =	\
-		-lpurple \
-		-lglib-2.0 \
-		-lgthread-2.0 \
-		-lgobject-2.0 \
-		-lgmodule-2.0 \
+
+PIDGIN_LIBS =	\
 		-lintl \
-		-lws2_32 \
-		-lwinmm \
-		-lz
-
-GTKPURPLES =	\
-		$(LIBPURPLES) \
+		-lglib-2.0 \
+		-lgobject-2.0 \
+		-lgthread-2.0 \
+		-lpurple \
+		-lz \
 		-lidletrack \
 		-lgtk-win32-2.0 \
 		-latk-1.0 \
 		-lpango-1.0 \
 		-lgdk-win32-2.0 \
 		-lgdk_pixbuf-2.0 \
-		-lgdi32
+		-lgdi32 \
+		-lwinmm
 
 include $(PIDGIN_COMMON_RULES)
 
@@ -159,7 +155,7 @@
 $(EXE_OBJECTS) $(PIDGIN_OBJECTS): $(PIDGIN_CONFIG_H)
 
 $(PIDGIN_TARGET).dll $(PIDGIN_TARGET).dll.a: $(PURPLE_DLL).a $(PIDGIN_IDLETRACK_DLL).a $(PIDGIN_OBJECTS)
-	$(CC) -shared $(PIDGIN_OBJECTS) $(LIB_PATHS) $(GTKPURPLES) $(DLL_LD_FLAGS) -Wl,--out-implib,$(PIDGIN_TARGET).dll.a -o $(PIDGIN_TARGET).dll
+	$(CC) -shared $(PIDGIN_OBJECTS) $(LIB_PATHS) $(PIDGIN_LIBS) $(DLL_LD_FLAGS) -Wl,--output-def,$(PIDGIN_TARGET).def,--out-implib,$(PIDGIN_TARGET).dll.a -o $(PIDGIN_TARGET).dll
 
 $(EXE_TARGET).exe: $(PIDGIN_CONFIG_H) $(PIDGIN_DLL).a $(PIDGIN_IDLETRACK_DLL).a $(EXE_OBJECTS)
 	$(CC) $(LDFLAGS) $(EXE_OBJECTS) -o $(EXE_TARGET).exe
--- a/pidgin/gtkaccount.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/gtkaccount.c	Mon Jun 18 01:48:35 2007 +0000
@@ -184,6 +184,7 @@
 	gtk_size_group_add_widget(dialog->sg, label);
 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+	gtk_label_set_mnemonic_widget(GTK_LABEL(label), widget);
 	gtk_widget_show(label);
 
 	gtk_box_pack_start(GTK_BOX(hbox), widget, TRUE, TRUE, PIDGIN_HIG_BORDER);
@@ -426,15 +427,18 @@
 		gtk_widget_ref(dialog->protocol_menu);
 	}
 
-	hbox = add_pref_box(dialog, vbox, _("Protocol:"), dialog->protocol_menu);
+	hbox = add_pref_box(dialog, vbox, _("Pro_tocol:"), dialog->protocol_menu);
 	g_object_set_data(G_OBJECT(dialog->protocol_menu), "container", hbox);
 
 	gtk_widget_unref(dialog->protocol_menu);
 
 	/* Screen name */
 	dialog->screenname_entry = gtk_entry_new();
-
-	add_pref_box(dialog, vbox, _("Screen name:"), dialog->screenname_entry);
+#if GTK_CHECK_VERSION(2,10,0)
+	g_object_set(G_OBJECT(dialog->screenname_entry), "truncate-multiline", TRUE, NULL);
+#endif
+
+	add_pref_box(dialog, vbox, _("Screen _name:"), dialog->screenname_entry);
 
 	g_signal_connect(G_OBJECT(dialog->screenname_entry), "changed",
 					 G_CALLBACK(screenname_changed_cb), dialog);
@@ -457,7 +461,7 @@
 		PurpleAccountUserSplit *split = l->data;
 		char *buf;
 
-		buf = g_strdup_printf("%s:", purple_account_user_split_get_text(split));
+		buf = g_strdup_printf("_%s:", purple_account_user_split_get_text(split));
 
 		entry = gtk_entry_new();
 
@@ -497,8 +501,8 @@
 		menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(dialog->protocol_menu));
 		item = gtk_menu_get_active(GTK_MENU(menu));
 		protocol = g_object_get_data(G_OBJECT(item), "protocol");
-		if (value == NULL && !strcmp(protocol, "prpl-fake") && 
-			!strcmp(purple_account_user_split_get_text(split), _("Domain")))
+		if (value == NULL && protocol != NULL && !strcmp(protocol, "prpl-fake") &&
+				!strcmp(purple_account_user_split_get_text(split), _("Domain")))
 			value = "gmail.com";
 
 		if (value != NULL)
@@ -516,16 +520,16 @@
 	gtk_entry_set_visibility(GTK_ENTRY(dialog->password_entry), FALSE);
 	if (gtk_entry_get_invisible_char(GTK_ENTRY(dialog->password_entry)) == '*')
 		gtk_entry_set_invisible_char(GTK_ENTRY(dialog->password_entry), PIDGIN_INVISIBLE_CHAR);
-	dialog->password_box = add_pref_box(dialog, vbox, _("Password:"),
+	dialog->password_box = add_pref_box(dialog, vbox, _("_Password:"),
 										  dialog->password_entry);
 
 	/* Alias */
 	dialog->alias_entry = gtk_entry_new();
-	add_pref_box(dialog, vbox, _("Local alias:"), dialog->alias_entry);
+	add_pref_box(dialog, vbox, _("_Local alias:"), dialog->alias_entry);
 
 	/* Remember Password */
 	dialog->remember_pass_check =
-		gtk_check_button_new_with_label(_("Remember password"));
+		gtk_check_button_new_with_mnemonic(_("Remember pass_word"));
 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dialog->remember_pass_check),
 								 FALSE);
 	gtk_box_pack_start(GTK_BOX(vbox), dialog->remember_pass_check,
@@ -596,12 +600,12 @@
 
 	/* New mail notifications */
 	dialog->new_mail_check =
-		gtk_check_button_new_with_label(_("New mail notifications"));
+		gtk_check_button_new_with_mnemonic(_("New _mail notifications"));
 	gtk_box_pack_start(GTK_BOX(vbox), dialog->new_mail_check, FALSE, FALSE, 0);
 	gtk_widget_show(dialog->new_mail_check);
 
 	/* Buddy icon */
-	dialog->icon_check = gtk_check_button_new_with_label(_("Use this buddy icon for this account:"));
+	dialog->icon_check = gtk_check_button_new_with_mnemonic(_("Use this buddy _icon for this account:"));
 	g_signal_connect(G_OBJECT(dialog->icon_check), "toggled", G_CALLBACK(icon_check_cb), dialog);
 	gtk_widget_show(dialog->icon_check);
 	gtk_box_pack_start(GTK_BOX(vbox), dialog->icon_check, FALSE, FALSE, 0);
@@ -698,7 +702,7 @@
 	PurpleKeyValuePair *kvp;
 	GList *l;
 	char buf[1024];
-	char *title;
+	char *title, *tmp;
 	const char *str_value, *protocol;
 	gboolean bool_value;
 
@@ -755,8 +759,9 @@
 						purple_account_option_get_default_bool(option));
 				}
 
-				check = gtk_check_button_new_with_label(
-					purple_account_option_get_text(option));
+				tmp = g_strconcat("_", purple_account_option_get_text(option), NULL);
+				check = gtk_check_button_new_with_mnemonic(tmp);
+				g_free(tmp);
 
 				gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check),
 											 bool_value);
@@ -788,7 +793,7 @@
 				entry = gtk_entry_new();
 				gtk_entry_set_text(GTK_ENTRY(entry), buf);
 
-				title = g_strdup_printf("%s:",
+				title = g_strdup_printf("_%s:",
 						purple_account_option_get_text(option));
 
 				add_pref_box(dialog, vbox, title, entry);
@@ -826,14 +831,14 @@
 				menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(dialog->protocol_menu));
 				item = gtk_menu_get_active(GTK_MENU(menu));
 				protocol = g_object_get_data(G_OBJECT(item), "protocol");
-				if (str_value == NULL && !strcmp(protocol, "prpl-fake") &&
+				if (str_value == NULL && protocol != NULL && !strcmp(protocol, "prpl-fake") &&
 					!strcmp(_("Connect server"),  purple_account_option_get_text(option)))
-					str_value = "talk.google.com";	
-		
+					str_value = "talk.google.com";
+
 				if (str_value != NULL)
 					gtk_entry_set_text(GTK_ENTRY(entry), str_value);
 
-				title = g_strdup_printf("%s:",
+				title = g_strdup_printf("_%s:",
 						purple_account_option_get_text(option));
 
 				add_pref_box(dialog, vbox, title, entry);
@@ -894,7 +899,7 @@
 				gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo),
 						renderer, "text", 0, NULL);
 
-				title = g_strdup_printf("%s:",
+				title = g_strdup_printf("_%s:",
 						purple_account_option_get_text(option));
 
 				add_pref_box(dialog, vbox, title, combo);
@@ -2024,19 +2029,26 @@
 {
 	GdkPixbuf *pixbuf, *buddyicon = NULL;
 	PurpleStoredImage *img = NULL;
+	PurplePlugin *prpl;
+	PurplePluginProtocolInfo *prpl_info = NULL;
 
 	pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_MEDIUM);
 	if ((pixbuf != NULL) && purple_account_is_disconnected(account))
 		gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE);
 
-	if (purple_account_get_bool(account, "use-global-buddyicon", TRUE)) {
-		if (global_buddyicon != NULL)
-			buddyicon = g_object_ref(G_OBJECT(global_buddyicon));
-		/* This is for when set_account() is called for a single account */
-		else
+	prpl = purple_find_prpl(purple_account_get_protocol_id(account));
+	if (prpl != NULL)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
+	if (prpl_info != NULL && prpl_info->icon_spec.format != NULL) {
+		if (purple_account_get_bool(account, "use-global-buddyicon", TRUE)) {
+			if (global_buddyicon != NULL)
+				buddyicon = g_object_ref(G_OBJECT(global_buddyicon));
+			/* This is for when set_account() is called for a single account */
+			else
+				img = purple_buddy_icons_find_account_icon(account);
+		} else {
 			img = purple_buddy_icons_find_account_icon(account);
-	} else {
-		img = purple_buddy_icons_find_account_icon(account);
+		}
 	}
 
 	if (img != NULL) {
--- a/pidgin/gtkblist.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/gtkblist.c	Mon Jun 18 01:48:35 2007 +0000
@@ -108,6 +108,7 @@
 
 static guint visibility_manager_count = 0;
 static gboolean gtk_blist_obscured = FALSE;
+static gboolean editing_blist = FALSE;
 
 static GList *pidgin_blist_sort_methods = NULL;
 static struct pidgin_blist_sort_method *current_sort_method = NULL;
@@ -266,8 +267,6 @@
 	purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/width",  event->width);
 	purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/height", event->height);
 
-	gtk_widget_set_size_request(gtkblist->headline_label,
-				    purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/width")-25,-1);
 	/* continue to handle event normally */
 	return FALSE;
 }
@@ -317,6 +316,12 @@
 	gtk_blist_join_chat(chat);
 }
 
+static void gtk_blist_renderer_editing_cancelled_cb(GtkCellRenderer *renderer, PurpleBuddyList *list)
+{
+	editing_blist = FALSE;
+	pidgin_blist_refresh(list);
+}
+
 static void gtk_blist_renderer_editing_started_cb(GtkCellRenderer *renderer,
 		GtkCellEditable *editable,
 		gchar *path_str,
@@ -353,10 +358,11 @@
 		GtkEntry *entry = GTK_ENTRY (editable);
 		gtk_entry_set_text(entry, text);
 	}
+	editing_blist = TRUE;
 }
 
 static void gtk_blist_renderer_edited_cb(GtkCellRendererText *text_rend, char *arg1,
-					 char *arg2, gpointer nada)
+					 char *arg2, PurpleBuddyList *list)
 {
 	GtkTreeIter iter;
 	GtkTreePath *path;
@@ -364,6 +370,7 @@
 	PurpleBlistNode *node;
 	PurpleGroup *dest;
 
+	editing_blist = FALSE;
 	path = gtk_tree_path_new_from_string (arg1);
 	gtk_tree_model_get_iter (GTK_TREE_MODEL(gtkblist->treemodel), &iter, path);
 	gtk_tree_path_free (path);
@@ -408,6 +415,7 @@
 		default:
 			break;
 	}
+	pidgin_blist_refresh(list);
 }
 
 static void gtk_blist_menu_alias_cb(GtkWidget *w, PurpleBlistNode *node)
@@ -490,7 +498,7 @@
 
 static void gtk_blist_show_onlinehelp_cb()
 {
-	purple_notify_uri(NULL, PURPLE_WEBSITE "documentation.php");
+	purple_notify_uri(NULL, PURPLE_WEBSITE "documentation");
 }
 
 static void
@@ -1129,10 +1137,10 @@
 	if (((PurpleBlistNode*)buddy)->parent->child->next && !sub && !contact_expanded) {
 		pidgin_separator(menu);
 		pidgin_append_blist_node_privacy_menu(menu, (PurpleBlistNode *)buddy);
-		pidgin_new_item_from_stock(menu, _("Alias..."), PIDGIN_STOCK_ALIAS,
+		pidgin_new_item_from_stock(menu, _("_Alias..."), PIDGIN_STOCK_ALIAS,
 				G_CALLBACK(gtk_blist_menu_alias_cb),
 				contact, 0, 0, NULL);
-		pidgin_new_item_from_stock(menu, _("Remove"), GTK_STOCK_REMOVE,
+		pidgin_new_item_from_stock(menu, _("_Remove"), GTK_STOCK_REMOVE,
 				G_CALLBACK(pidgin_blist_remove_cb),
 				contact, 0, 0, NULL);
 	} else if (!sub || contact_expanded) {
@@ -1174,7 +1182,7 @@
 			return FALSE;
 		}
 		if(buddy)
-			serv_get_info(buddy->account->gc, buddy->name);
+			gtk_blist_menu_info_cb(NULL, buddy);
 	} else if (event->keyval == GDK_F2) {
 		gtk_blist_menu_alias_cb(tv, node);
 	}
@@ -1428,7 +1436,7 @@
 			prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
 		if (prpl && prpl_info->get_info)
-			serv_get_info(b->account->gc, b->name);
+			gtk_blist_menu_info_cb(NULL, b);
 		handled = TRUE;
 	}
 
@@ -2726,6 +2734,7 @@
 {
 	GtkTreePath *path;
 	int delay;
+	GdkRectangle rect;
 
 	/*
 	 * When dragging a buddy into a contact, this is the delay before
@@ -2741,7 +2750,17 @@
 	}
 
 	gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), x, y, &path, NULL, NULL, NULL);
-	gtk_tree_view_get_cell_area(GTK_TREE_VIEW(tv), path, NULL, &gtkblist->tip_rect);
+	gtk_tree_view_get_cell_area(GTK_TREE_VIEW(tv), path, NULL, &rect);
+
+	/* Only autoexpand when in the middle of the cell to avoid annoying un-intended expands */
+	if (y < rect.y + (rect.height / 3) ||
+	    y > rect.y + (2 * (rect.height /3)))
+		return FALSE;
+	
+	rect.height = rect.height / 3;
+	rect.y += rect.height;
+
+	gtkblist->tip_rect = rect;
 
 	if (path)
 		gtk_tree_path_free(path);
@@ -2994,7 +3013,14 @@
 		signon = purple_presence_get_login_time(presence);
 		if (full && PURPLE_BUDDY_IS_ONLINE(b) && signon > 0)
 		{
-			tmp = purple_str_seconds_to_string(time(NULL) - signon);
+			if (time(NULL) - signon > 63072000 /* 2 years */) {
+				/*
+				 * Our local clock must be wrong, show the actual
+				 * date instead of "4 days", etc.
+				 */
+				tmp = g_strdup(purple_date_format_long(localtime(&signon)));
+			} else
+				tmp = purple_str_seconds_to_string(time(NULL) - signon);
 			purple_notify_user_info_add_pair(user_info, _("Logged In"), tmp);
 			g_free(tmp);
 		}
@@ -3244,6 +3270,9 @@
 		else if (purple_presence_is_idle(p) && size == PIDGIN_STATUS_ICON_SMALL)
 			ret = gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_AVAILABLE_I,
 					icon_size, "GtkTreeView");
+		else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_INVISIBLE))
+			ret = gtk_widget_render_icon(GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_INVISIBLE,
+					icon_size, "GtkTreeView");
 		else
 			ret = gtk_widget_render_icon(GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_AVAILABLE,
 					icon_size, "GtkTreeView");
@@ -3413,8 +3442,16 @@
 				"<span color='%s' size='smaller'>%s</span>",
 				dim_grey(), esc, dim_grey(),
 				statustext != NULL ? statustext : "");
-	}
-
+	} else if (!PURPLE_BUDDY_IS_ONLINE(b)) {
+		if (!selected && !statustext) /* We handle selected text later */
+			text = g_strdup_printf("<span color='%s'>%s</span>", dim_grey(), esc);
+		else if (!selected && !text)
+			text = g_strdup_printf("<span color='%s'>%s</span>\n"
+				"<span color='%s' size='smaller'>%s</span>",
+				dim_grey(), esc, dim_grey(),
+				statustext != NULL ? statustext : "");
+
+	}
 	/* Not idle and not selected */
 	else if (!selected && !text)
 	{
@@ -3722,8 +3759,11 @@
 
 gboolean pidgin_blist_node_is_contact_expanded(PurpleBlistNode *node)
 {
-	if PURPLE_BLIST_NODE_IS_BUDDY(node)
+	if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
 		node = node->parent;
+		if (node == NULL)
+			return FALSE;
+	}
 
 	g_return_val_if_fail(PURPLE_BLIST_NODE_IS_CONTACT(node), FALSE);
 
@@ -4429,7 +4469,8 @@
 										"markup", NAME_COLUMN,
 										NULL);
 	g_signal_connect(G_OBJECT(rend), "editing-started", G_CALLBACK(gtk_blist_renderer_editing_started_cb), NULL);
-	g_signal_connect(G_OBJECT(rend), "edited", G_CALLBACK(gtk_blist_renderer_edited_cb), NULL);
+	g_signal_connect(G_OBJECT(rend), "editing-canceled", G_CALLBACK(gtk_blist_renderer_editing_cancelled_cb), list);
+	g_signal_connect(G_OBJECT(rend), "edited", G_CALLBACK(gtk_blist_renderer_edited_cb), list);
 	g_object_set(rend, "ypad", 0, "yalign", 0.5, NULL);
 #if GTK_CHECK_VERSION(2,6,0)
 	g_object_set(rend, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
@@ -4724,8 +4765,15 @@
 				NODE_COLUMN, &new_selection, -1);
 	}
 
-	/* we set this up as a timeout, otherwise the blist flickers */
-	g_timeout_add(0, (GSourceFunc)do_selection_changed, new_selection);
+	/* we set this up as a timeout, otherwise the blist flickers ...
+	 * but we don't do it for groups, because it causes total bizarness -
+	 * the previously selected buddy node might rendered at half height.
+	 */
+	if ((new_selection != NULL) && PURPLE_BLIST_NODE_IS_GROUP(new_selection)) {
+		do_selection_changed(new_selection);
+	} else {
+		g_timeout_add(0, (GSourceFunc)do_selection_changed, new_selection);
+	}
 }
 
 static gboolean insert_node(PurpleBuddyList *list, PurpleBlistNode *node, GtkTreeIter *iter)
@@ -4764,9 +4812,10 @@
 
 	gtk_tree_path_free(newpath);
 
-	gtk_tree_store_set(gtkblist->treemodel, iter,
-			NODE_COLUMN, node,
-			-1);
+	if (!editing_blist)
+		gtk_tree_store_set(gtkblist->treemodel, iter,
+				NODE_COLUMN, node,
+				-1);
 
 	if(node->parent) {
 		GtkTreePath *expand = NULL;
@@ -4799,6 +4848,9 @@
 
 	g_return_if_fail(node != NULL);
 
+	if (editing_blist)
+		return;
+	
 	if (PURPLE_BLIST_NODE_IS_GROUP(node))
 		gnode = node;
 	else if (PURPLE_BLIST_NODE_IS_BUDDY(node))
@@ -4850,7 +4902,7 @@
 				   GROUP_EXPANDER_VISIBLE_COLUMN, TRUE,
 				   CONTACT_EXPANDER_VISIBLE_COLUMN, FALSE,
 				   BUDDY_ICON_VISIBLE_COLUMN, FALSE,
-				   IDLE_VISIBLE_COLUMN, FALSE,
+			   	   IDLE_VISIBLE_COLUMN, FALSE,
 				   EMBLEM_VISIBLE_COLUMN, FALSE,
 				   -1);
 		g_free(title);
@@ -4900,6 +4952,9 @@
 	gboolean biglist = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons");
 	presence = purple_buddy_get_presence(buddy);
 
+	if (editing_blist)
+		return;
+	
 	status = pidgin_blist_get_status_icon((PurpleBlistNode*)buddy,
 						PIDGIN_STATUS_ICON_SMALL);
 
@@ -4945,7 +5000,6 @@
 			idle = i2;
 		}
 	}
-
 	gtk_tree_store_set(gtkblist->treemodel, iter,
 			   STATUS_ICON_COLUMN, status,
 			   STATUS_ICON_VISIBLE_COLUMN, TRUE,
@@ -4960,7 +5014,7 @@
 			   CONTACT_EXPANDER_COLUMN, NULL,
 			   CONTACT_EXPANDER_VISIBLE_COLUMN, expanded,
 			   GROUP_EXPANDER_VISIBLE_COLUMN, FALSE,
-			-1);
+   			   -1);
 
 	g_free(mark);
 	g_free(idle);
@@ -4979,6 +5033,9 @@
 	PurpleBuddy *buddy;
 	struct _pidgin_blist_node *gtknode;
 
+	if (editing_blist)
+		return;
+
 	if (PURPLE_BLIST_NODE_IS_BUDDY(node))
 		cnode = node->parent;
 	else
@@ -5075,6 +5132,9 @@
 
 	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
 
+	if (editing_blist)
+		return;
+
 	/* First things first, update the group */
 	pidgin_blist_update_group(list, node->parent);
 
@@ -5386,12 +5446,25 @@
 	gtk_container_set_border_width(GTK_CONTAINER(table), 0);
 	gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
 
-	label = gtk_label_new(_("Screen name:"));
+	/* Set up stuff for the account box */
+	label = gtk_label_new_with_mnemonic(_("_Account:"));
 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 	gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
 
+	data->account_box = pidgin_account_option_menu_new(account, FALSE,
+			G_CALLBACK(add_buddy_select_account_cb), NULL, data);
+
+	gtk_table_attach_defaults(GTK_TABLE(table), data->account_box, 1, 2, 0, 1);
+	gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->account_box);
+	pidgin_set_accessible_label (data->account_box, label);
+	/* End of account box */
+
+	label = gtk_label_new_with_mnemonic(_("_Screen name:"));
+	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+	gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2);
+
 	data->entry = gtk_entry_new();
-	gtk_table_attach_defaults(GTK_TABLE(table), data->entry, 1, 2, 0, 1);
+	gtk_table_attach_defaults(GTK_TABLE(table), data->entry, 1, 2, 1, 2);
 	gtk_widget_grab_focus(data->entry);
 
 	if (username != NULL)
@@ -5401,19 +5474,20 @@
 										  GTK_RESPONSE_OK, FALSE);
 
 	gtk_entry_set_activates_default (GTK_ENTRY(data->entry), TRUE);
+	gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->entry);
 	pidgin_set_accessible_label (data->entry, label);
 
 	g_signal_connect(G_OBJECT(data->entry), "changed",
 					 G_CALLBACK(pidgin_set_sensitive_if_input),
 					 data->window);
 
-	label = gtk_label_new(_("Alias:"));
+	label = gtk_label_new_with_mnemonic(_("A_lias:"));
 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-	gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2);
+	gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3);
 
 	data->entry_for_alias = gtk_entry_new();
 	gtk_table_attach_defaults(GTK_TABLE(table),
-							  data->entry_for_alias, 1, 2, 1, 2);
+							  data->entry_for_alias, 1, 2, 2, 3);
 
 	if (alias != NULL)
 		gtk_entry_set_text(GTK_ENTRY(data->entry_for_alias), alias);
@@ -5422,29 +5496,19 @@
 		gtk_widget_grab_focus(GTK_WIDGET(data->entry_for_alias));
 
 	gtk_entry_set_activates_default (GTK_ENTRY(data->entry_for_alias), TRUE);
+	gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->entry_for_alias);
 	pidgin_set_accessible_label (data->entry_for_alias, label);
 
-	label = gtk_label_new(_("Group:"));
+	label = gtk_label_new_with_mnemonic(_("_Group:"));
 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-	gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3);
+	gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4);
 
 	data->combo = gtk_combo_new();
 	gtk_combo_set_popdown_strings(GTK_COMBO(data->combo), groups_tree());
-	gtk_table_attach_defaults(GTK_TABLE(table), data->combo, 1, 2, 2, 3);
+	gtk_table_attach_defaults(GTK_TABLE(table), data->combo, 1, 2, 3, 4);
+	gtk_label_set_mnemonic_widget(GTK_LABEL(label), GTK_COMBO(data->combo)->entry);
 	pidgin_set_accessible_label (data->combo, label);
 
-	/* Set up stuff for the account box */
-	label = gtk_label_new(_("Account:"));
-	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-	gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4);
-
-	data->account_box = pidgin_account_option_menu_new(account, FALSE,
-			G_CALLBACK(add_buddy_select_account_cb), NULL, data);
-
-	gtk_table_attach_defaults(GTK_TABLE(table), data->account_box, 1, 2, 3, 4);
-	pidgin_set_accessible_label (data->account_box, label);
-	/* End of account box */
-
 	g_signal_connect(G_OBJECT(data->window), "response",
 					 G_CALLBACK(add_buddy_cb), data);
 
@@ -5750,7 +5814,7 @@
 	rowbox = gtk_hbox_new(FALSE, 5);
 	gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0);
 
-	label = gtk_label_new(_("Account:"));
+	label = gtk_label_new_with_mnemonic(_("_Account:"));
 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 	gtk_size_group_add_widget(data->sg, label);
 	gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0);
@@ -5759,6 +5823,7 @@
 			G_CALLBACK(addchat_select_account_cb),
 			chat_account_filter_func, data);
 	gtk_box_pack_start(GTK_BOX(rowbox), data->account_menu, TRUE, TRUE, 0);
+	gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->account_menu);
 	pidgin_set_accessible_label (data->account_menu, label);
 
 	data->entries_box = gtk_vbox_new(FALSE, 5);
@@ -5770,7 +5835,7 @@
 	rowbox = gtk_hbox_new(FALSE, 5);
 	gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0);
 
-	label = gtk_label_new(_("Alias:"));
+	label = gtk_label_new_with_mnemonic(_("A_lias:"));
 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 	gtk_size_group_add_widget(data->sg, label);
 	gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0);
@@ -5780,12 +5845,15 @@
 		gtk_entry_set_text(GTK_ENTRY(data->alias_entry), alias);
 	gtk_box_pack_end(GTK_BOX(rowbox), data->alias_entry, TRUE, TRUE, 0);
 	gtk_entry_set_activates_default(GTK_ENTRY(data->alias_entry), TRUE);
+	gtk_label_set_mnemonic_widget(GTK_LABEL(label), data->alias_entry);
 	pidgin_set_accessible_label (data->alias_entry, label);
+	if (name != NULL)
+		gtk_widget_grab_focus(data->alias_entry);
 
 	rowbox = gtk_hbox_new(FALSE, 5);
 	gtk_box_pack_start(GTK_BOX(vbox), rowbox, FALSE, FALSE, 0);
 
-	label = gtk_label_new(_("Group:"));
+	label = gtk_label_new_with_mnemonic(_("_Group:"));
 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
 	gtk_size_group_add_widget(data->sg, label);
 	gtk_box_pack_start(GTK_BOX(rowbox), label, FALSE, FALSE, 0);
@@ -5799,6 +5867,7 @@
 		gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(data->group_combo)->entry),
 						   group->name);
 	}
+	gtk_label_set_mnemonic_widget(GTK_LABEL(label), GTK_COMBO(data->group_combo)->entry);
 	pidgin_set_accessible_label (data->group_combo, label);
 
 	g_signal_connect(G_OBJECT(data->window), "response",
--- a/pidgin/gtkconv.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/gtkconv.c	Mon Jun 18 01:48:35 2007 +0000
@@ -49,6 +49,7 @@
 #include "prpl.h"
 #include "request.h"
 #include "util.h"
+#include "version.h"
 
 #include "gtkdnd-hints.h"
 #include "gtkblist.h"
@@ -235,6 +236,10 @@
 		return FALSE;
 	}
 
+	if (gdk_window_get_state(gtkconv->win->window->window) & GDK_WINDOW_STATE_MAXIMIZED) {
+		return FALSE;
+	}
+
 	/* I find that I resize the window when it has a bunch of conversations in it, mostly so that the
 	 * tab bar will fit, but then I don't want new windows taking up the entire screen.  I check to see
 	 * if there is only one conversation in the window.  This way we'll be setting new windows to the
@@ -1243,6 +1248,37 @@
 }
 
 static void
+menu_insert_link_cb(gpointer data, guint action, GtkWidget *widget)
+{
+	PidginWindow *win = data;
+	PidginConversation *gtkconv;
+	GtkIMHtmlToolbar *toolbar;
+
+	gtkconv = pidgin_conv_window_get_active_gtkconv(win);
+	toolbar = GTK_IMHTMLTOOLBAR(gtkconv->toolbar);
+
+	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toolbar->link),
+			!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toolbar->link)));
+}
+
+static void
+menu_insert_image_cb(gpointer data, guint action, GtkWidget *widget)
+{
+	PidginWindow *win = data;
+	PurpleConversation *conv;
+	PidginConversation *gtkconv;
+	GtkIMHtmlToolbar *toolbar;
+
+	gtkconv = pidgin_conv_window_get_active_gtkconv(win);
+	conv    = gtkconv->active_conv;
+	toolbar = GTK_IMHTMLTOOLBAR(gtkconv->toolbar);
+
+	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toolbar->image),
+			!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toolbar->image)));
+}
+
+
+static void
 menu_alias_cb(gpointer data, guint action, GtkWidget *widget)
 {
 	PidginWindow *win = data;
@@ -1821,6 +1857,9 @@
 				if (!gtkconv->send_history)
 					break;
 
+				if (gtkconv->entry != entry)
+					break;
+
 				if (!gtkconv->send_history->prev) {
 					GtkTextIter start, end;
 
@@ -1869,6 +1908,9 @@
 				if (!gtkconv->send_history)
 					break;
 
+				if (gtkconv->entry != entry)
+					break;
+
 				if (gtkconv->send_history->prev && gtkconv->send_history->prev->data) {
 					GObject *object;
 					GtkTextIter iter;
@@ -1972,6 +2014,8 @@
 		switch (event->keyval)
 		{
 			case GDK_Tab:
+				if (gtkconv->entry != entry)
+					break;
 				return tab_complete(conv);
 				break;
 
@@ -2048,6 +2092,9 @@
 	return TRUE;
 }
 
+static void
+regenerate_options_items(PidginWindow *win);
+
 void
 pidgin_conv_switch_active_conversation(PurpleConversation *conv)
 {
@@ -2148,6 +2195,8 @@
 
 	gray_stuff_out(gtkconv);
 	update_typing_icon(gtkconv);
+	g_object_set_data(G_OBJECT(entry), "transient_buddy", NULL);
+	regenerate_options_items(gtkconv->win);
 
 	gtk_window_set_title(GTK_WINDOW(gtkconv->win->window),
 	                     gtk_label_get_text(GTK_LABEL(gtkconv->tab_label)));
@@ -2814,6 +2863,14 @@
 
 	{ "/Conversation/sep3", NULL, NULL, 0, "<Separator>", NULL },
 
+	{ N_("/Conversation/Insert Lin_k..."), NULL, menu_insert_link_cb, 0,
+		"<StockItem>", PIDGIN_STOCK_TOOLBAR_INSERT_LINK },
+	{ N_("/Conversation/Insert Imag_e..."), NULL, menu_insert_image_cb, 0,
+		"<StockItem>", PIDGIN_STOCK_TOOLBAR_INSERT_IMAGE },
+
+	{ "/Conversation/sep4", NULL, NULL, 0, "<Separator>", NULL },
+
+
 	{ N_("/Conversation/_Close"), NULL, menu_close_conv_cb, 0,
 			"<StockItem>", GTK_STOCK_CLOSE },
 
@@ -2893,14 +2950,59 @@
 	GList *list;
 	PidginConversation *gtkconv;
 	PurpleConversation *conv;
-	PurpleBuddy *buddy;
+	PurpleBlistNode *node = NULL;
+	PurpleChat *chat = NULL;
+	PurpleBuddy *buddy = NULL;
 
 	gtkconv = pidgin_conv_window_get_active_gtkconv(win);
 	conv = gtkconv->active_conv;
-	buddy = purple_find_buddy(conv->account, conv->name);
 
 	menu = gtk_item_factory_get_widget(win->menu.item_factory, N_("/Conversation/More"));
 
+	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
+		chat = purple_blist_find_chat(conv->account, conv->name);
+
+		if ((chat == NULL) && (gtkconv->imhtml != NULL)) {
+			chat = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_chat");
+		}
+
+		if ((chat == NULL) && (gtkconv->imhtml != NULL)) {
+			GHashTable *components;
+			components = g_hash_table_new_full(g_str_hash, g_str_equal,
+					g_free, g_free);
+			g_hash_table_replace(components, g_strdup("channel"),
+					g_strdup(conv->name));
+			chat = purple_chat_new(conv->account, NULL, components);
+			purple_blist_node_set_flags((PurpleBlistNode *)chat,
+					PURPLE_BLIST_NODE_FLAG_NO_SAVE);
+			g_object_set_data_full(G_OBJECT(gtkconv->imhtml), "transient_chat",
+					chat, (GDestroyNotify)purple_blist_remove_chat);
+		}
+	} else {
+		buddy = purple_find_buddy(conv->account, conv->name);
+
+		/* gotta remain bug-compatible :( libpurple < 2.0.2 didn't handle
+		 * removing "isolated" buddy nodes well */
+		if (purple_version_check(2, 0, 2) == NULL) {
+			if ((buddy == NULL) && (gtkconv->imhtml != NULL)) {
+				buddy = g_object_get_data(G_OBJECT(gtkconv->imhtml), "transient_buddy");
+			}
+
+			if ((buddy == NULL) && (gtkconv->imhtml != NULL)) {
+				buddy = purple_buddy_new(conv->account, conv->name, NULL);
+				purple_blist_node_set_flags((PurpleBlistNode *)buddy,
+						PURPLE_BLIST_NODE_FLAG_NO_SAVE);
+				g_object_set_data_full(G_OBJECT(gtkconv->imhtml), "transient_buddy",
+						buddy, (GDestroyNotify)purple_blist_remove_buddy);
+			}
+		}
+	}
+
+	if (chat)
+		node = (PurpleBlistNode *)chat;
+	else if (buddy)
+		node = (PurpleBlistNode *)buddy;
+
 	/* Remove the previous entries */
 	for (list = gtk_container_get_children(GTK_CONTAINER(menu)); list; )
 	{
@@ -2910,12 +3012,11 @@
 	}
 
 	/* Now add the stuff */
-	if (buddy)
+	if (node)
 	{
 		if (purple_account_is_connected(conv->account))
-			pidgin_append_blist_node_proto_menu(menu, conv->account->gc,
-												  (PurpleBlistNode *)buddy);
-		pidgin_append_blist_node_extended_menu(menu, (PurpleBlistNode *)buddy);
+			pidgin_append_blist_node_proto_menu(menu, conv->account->gc, node);
+		pidgin_append_blist_node_extended_menu(menu, node);
 	}
 
 	if ((list = gtk_container_get_children(GTK_CONTAINER(menu))) == NULL)
@@ -3028,6 +3129,18 @@
 		gtk_item_factory_get_widget(win->menu.item_factory,
 		                            N_("/Conversation/Remove..."));
 
+	/* --- */
+
+	win->menu.insert_link =
+		gtk_item_factory_get_widget(win->menu.item_factory,
+				N_("/Conversation/Insert Link..."));
+
+	win->menu.insert_image =
+		gtk_item_factory_get_widget(win->menu.item_factory,
+				N_("/Conversation/Insert Image..."));
+
+	/* --- */
+
 	win->menu.logging =
 		gtk_item_factory_get_widget(win->menu.item_factory,
 		                            N_("/Options/Enable Logging"));
@@ -4189,6 +4302,8 @@
 
 		gtk_box_pack_start(GTK_BOX(hbox), gtkchat->topic_text, TRUE, TRUE, 0);
 		gtk_widget_show(gtkchat->topic_text);
+		g_signal_connect(G_OBJECT(gtkchat->topic_text), "key_press_event",
+			             G_CALLBACK(entry_key_press_cb), gtkconv);
 	}
 
 	/* Setup the horizontal pane. */
@@ -5893,6 +6008,8 @@
 			gtk_widget_hide(win->menu.add);
 		}
 
+		gtk_widget_show(win->menu.insert_link);
+		gtk_widget_show(win->menu.insert_image);
 		gtk_widget_show(win->menu.show_icon);
 	} else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
 		/* Show stuff that applies to Chats, hide stuff that applies to IMs */
@@ -5918,6 +6035,8 @@
 			gtk_widget_show(win->menu.remove);
 		}
 
+		gtk_widget_show(win->menu.insert_link);
+		gtk_widget_show(win->menu.insert_image);
 	}
 
 	/*
@@ -5959,6 +6078,8 @@
 		gtk_widget_set_sensitive(win->menu.add_pounce, TRUE);
 		gtk_widget_set_sensitive(win->menu.get_info, (prpl_info->get_info != NULL));
 		gtk_widget_set_sensitive(win->menu.invite, (prpl_info->chat_invite != NULL));
+		gtk_widget_set_sensitive(win->menu.insert_link, (conv->features & PURPLE_CONNECTION_HTML));
+		gtk_widget_set_sensitive(win->menu.insert_image, (prpl_info->options & OPT_PROTO_IM_IMAGE) && !(conv->features & PURPLE_CONNECTION_NO_IMAGES));
 
 		if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)
 		{
@@ -5993,6 +6114,8 @@
 		gtk_widget_set_sensitive(win->menu.alias, FALSE);
 		gtk_widget_set_sensitive(win->menu.add, FALSE);
 		gtk_widget_set_sensitive(win->menu.remove, FALSE);
+		gtk_widget_set_sensitive(win->menu.insert_link, TRUE);
+		gtk_widget_set_sensitive(win->menu.insert_image, FALSE);
 	}
 
 	/*
@@ -6951,6 +7074,9 @@
 	purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/tab_side", GTK_POS_TOP);
 	purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/scrollback_lines", 4000);
 
+	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/use_theme_font", TRUE);
+	purple_prefs_add_string(PIDGIN_PREFS_ROOT "/conversations/custom_font", "");
+
 	/* Conversations -> Chat */
 	purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations/chat");
 	purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/default_width", 410);
@@ -7919,7 +8045,9 @@
 	entry = gtk_entry_new();
 	gtk_entry_set_has_frame(GTK_ENTRY(entry), FALSE);
 	gtk_entry_set_width_chars(GTK_ENTRY(entry), 10);
+#if GTK_CHECK_VERSION(2,4,0)
 	gtk_entry_set_alignment(GTK_ENTRY(entry), 0.5);
+#endif
 
 	gtk_box_pack_start(GTK_BOX(gtkconv->tabby), entry, TRUE, TRUE, 0);
 	/* after the tab label */
@@ -8326,7 +8454,9 @@
 	}
 
 	ebox = gtk_event_box_new();
+#if GTK_CHECK_VERSION(2,4,0)
 	gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE);
+#endif
 	gtk_container_add(GTK_CONTAINER(ebox), gtkconv->tabby);
 	g_signal_connect(G_OBJECT(ebox), "button-press-event",
 					G_CALLBACK(alias_double_click_cb), gtkconv);
--- a/pidgin/gtkdialogs.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/gtkdialogs.c	Mon Jun 18 01:48:35 2007 +0000
@@ -822,8 +822,17 @@
 	if (username != NULL && purple_str_has_suffix(username, "rocksmyworld"))
 		found = pidgin_dialogs_ee(username);
 
-	if (!found && username != NULL && *username != '\0' && account != NULL)
-		serv_get_info(purple_account_get_connection(account), username);
+	if (!found && username != NULL && *username != '\0' && account != NULL) {
+
+		PurpleConnection *gc = purple_account_get_connection(account);
+
+		PurpleNotifyUserInfo *info = purple_notify_user_info_new();
+		purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving..."));
+		purple_notify_userinfo(gc, username, info, NULL, NULL);
+		purple_notify_user_info_destroy(info);
+
+		serv_get_info(gc, username);
+	}
 
 	g_free(username);
 }
--- a/pidgin/gtkdialogs.h	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/gtkdialogs.h	Mon Jun 18 01:48:35 2007 +0000
@@ -36,10 +36,15 @@
 void pidgin_dialogs_im_with_user(PurpleAccount *, const char *);
 void pidgin_dialogs_info(void);
 void pidgin_dialogs_log(void);
+
+/**
+ * @deprecated This function is no longer used and will be removed in
+ *             Pidgin 3.0.0 unless there is sufficient demand to keep it.
+ */
 void pidgin_dialogs_alias_contact(PurpleContact *);
+
 void pidgin_dialogs_alias_buddy(PurpleBuddy *);
 void pidgin_dialogs_alias_chat(PurpleChat *);
-
 void pidgin_dialogs_remove_buddy(PurpleBuddy *);
 void pidgin_dialogs_remove_group(PurpleGroup *);
 void pidgin_dialogs_remove_chat(PurpleChat *);
--- a/pidgin/gtkdocklet-x11.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/gtkdocklet-x11.c	Mon Jun 18 01:48:35 2007 +0000
@@ -125,8 +125,12 @@
 		int icon_size;
 		if (docklet_height < 22)
 			icon_size = gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL);
+		else if (docklet_height < 32)
+			icon_size = gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_SMALL);
+		else if (docklet_height < 48)
+			icon_size = gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_MEDIUM);
 		else
-			icon_size = gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_SMALL);
+			icon_size = gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_LARGE);
 
 		gtk_image_set_from_stock(GTK_IMAGE(image), icon_name, icon_size);
 	}
@@ -281,7 +285,7 @@
 	 * The x11 docklet tracks whether it successfully embedded in a pref and
 	 * allows for a longer timeout period if it successfully embedded the last
 	 * time it was run. This should hopefully solve problems with the buddy
-	 * list not properly starting hidden when gaim is started on login.
+	 * list not properly starting hidden when Pidgin is started on login.
 	 */
 	if(!recreate) {
 		pidgin_docklet_embedded();
--- a/pidgin/gtkft.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/gtkft.c	Mon Jun 18 01:48:35 2007 +0000
@@ -248,10 +248,10 @@
 
 	get_xfer_info_strings(xfer, &kbsec, &time_elapsed, &time_remaining);
 
-	status = g_strdup_printf("%ld%% (%ld of %ld bytes)",
-							 (unsigned long)(purple_xfer_get_progress(xfer)*100),
-							 (unsigned long)purple_xfer_get_bytes_sent(xfer),
-							 (unsigned long)purple_xfer_get_size(xfer));
+	status = g_strdup_printf("%d%% (%" G_GSIZE_FORMAT " of %" G_GSIZE_FORMAT " bytes)",
+							 (int)(purple_xfer_get_progress(xfer)*100),
+							 purple_xfer_get_bytes_sent(xfer),
+							 purple_xfer_get_size(xfer));
 
 	if (purple_xfer_is_completed(xfer)) {
 
--- a/pidgin/gtkimhtml.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/gtkimhtml.c	Mon Jun 18 01:48:35 2007 +0000
@@ -140,6 +140,10 @@
 };
 static guint signals [LAST_SIGNAL] = { 0 };
 
+static char *html_clipboard = NULL;
+static char *text_clipboard = NULL;
+GtkClipboard *clipboard_selection = NULL;
+
 static GtkTargetEntry selection_targets[] = {
 #ifndef _WIN32
 	{ "text/html", 0, TARGET_HTML },
@@ -871,14 +875,17 @@
 
 static void gtk_imhtml_clipboard_get(GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, GtkIMHtml *imhtml) {
 	char *text = NULL;
-	gboolean primary;
+	gboolean primary = (clipboard != clipboard_selection);
 	GtkTextIter start, end;
-	GtkTextMark *sel = gtk_text_buffer_get_selection_bound(imhtml->text_buffer);
-	GtkTextMark *ins = gtk_text_buffer_get_insert(imhtml->text_buffer);
-
-	gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &start, sel);
-	gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &end, ins);
-	primary = gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_PRIMARY) == clipboard;
+	GtkTextMark *sel = NULL;
+	GtkTextMark *ins = NULL; 
+
+	if (primary) { 
+		ins = gtk_text_buffer_get_insert(imhtml->text_buffer);
+		sel = gtk_text_buffer_get_selection_bound(imhtml->text_buffer);
+		gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &start, sel);
+		gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &end, ins);
+	}
 
 	if (info == TARGET_HTML) {
 		char *selection;
@@ -888,7 +895,7 @@
 		if (primary) {
 			text = gtk_imhtml_get_markup_range(imhtml, &start, &end);
 		} else
-			text = imhtml->clipboard_html_string;
+			text = html_clipboard;
 
 		/* Mozilla asks that we start our text/html with the Unicode byte order mark */
 		str = g_string_append_unichar(str, 0xfeff);
@@ -906,7 +913,7 @@
 		if (primary) {
 			text = gtk_imhtml_get_text(imhtml, &start, &end);
 		} else
-			text = imhtml->clipboard_text_string;
+			text = text_clipboard;
 		gtk_selection_data_set_text(selection_data, text, strlen(text));
 	}
 	if (primary) /* This was allocated here */
@@ -929,20 +936,32 @@
 					   &insert);
 }
 
+static void gtk_imhtml_clipboard_clear (GtkClipboard *clipboard, GtkSelectionData *sel_data,
+				 guint info, gpointer user_data_or_owner)
+{
+	clipboard_selection = NULL;
+}
+
 static void copy_clipboard_cb(GtkIMHtml *imhtml, gpointer unused)
 {
 	GtkTextIter start, end;
 	if (gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) {
-		gtk_clipboard_set_with_owner(gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD),
+		if (!clipboard_selection)
+			clipboard_selection = gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD);
+		gtk_clipboard_set_with_owner(clipboard_selection,
 						 selection_targets, sizeof(selection_targets) / sizeof(GtkTargetEntry),
 						 (GtkClipboardGetFunc)gtk_imhtml_clipboard_get,
-						 (GtkClipboardClearFunc)NULL, G_OBJECT(imhtml));
+						 (GtkClipboardClearFunc)gtk_imhtml_clipboard_clear, G_OBJECT(imhtml));
 
 		g_free(imhtml->clipboard_html_string);
 		g_free(imhtml->clipboard_text_string);
 
 		imhtml->clipboard_html_string = gtk_imhtml_get_markup_range(imhtml, &start, &end);
 		imhtml->clipboard_text_string = gtk_imhtml_get_text(imhtml, &start, &end);
+
+		text_clipboard = imhtml->clipboard_text_string;
+		html_clipboard = imhtml->clipboard_html_string;
+	
 	}
 
 	g_signal_stop_emission_by_name(imhtml, "copy-clipboard");
@@ -952,10 +971,12 @@
 {
 	GtkTextIter start, end;
 	if (gtk_text_buffer_get_selection_bounds(imhtml->text_buffer, &start, &end)) {
-		gtk_clipboard_set_with_owner(gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD),
+		if (!clipboard_selection)
+			clipboard_selection = gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_CLIPBOARD);
+		gtk_clipboard_set_with_owner(clipboard_selection,
 						 selection_targets, sizeof(selection_targets) / sizeof(GtkTargetEntry),
 						 (GtkClipboardGetFunc)gtk_imhtml_clipboard_get,
-						 (GtkClipboardClearFunc)NULL, G_OBJECT(imhtml));
+						 (GtkClipboardClearFunc)gtk_imhtml_clipboard_clear, G_OBJECT(imhtml));
 
 		g_free(imhtml->clipboard_html_string);
 		g_free(imhtml->clipboard_text_string);
@@ -963,6 +984,9 @@
 		imhtml->clipboard_html_string = gtk_imhtml_get_markup_range(imhtml, &start, &end);
 		imhtml->clipboard_text_string = gtk_imhtml_get_text(imhtml, &start, &end);
 
+		text_clipboard = imhtml->clipboard_text_string;
+		html_clipboard = imhtml->clipboard_html_string;
+
 		if (imhtml->editable)
 			gtk_text_buffer_delete_selection(imhtml->text_buffer, FALSE, FALSE);
 	}
@@ -1199,17 +1223,18 @@
 		g_free(img_data);
 	}
 
-	if (imhtml->clipboard_text_string) {
-		g_free(imhtml->clipboard_text_string);
-		g_free(imhtml->clipboard_html_string);
-	}
-
 	g_list_free(imhtml->scalables);
 	g_slist_free(imhtml->im_images);
 	g_queue_free(imhtml->animations);
 	g_free(imhtml->protocol_name);
 	g_free(imhtml->search_string);
 	G_OBJECT_CLASS(parent_class)->finalize (object);
+	if (clipboard_selection)
+		gtk_clipboard_set_with_owner(clipboard_selection,
+        	                             selection_targets, sizeof(selection_targets) / sizeof(GtkTargetEntry),
+                	                     (GtkClipboardGetFunc)gtk_imhtml_clipboard_get,
+                        	             (GtkClipboardClearFunc)NULL, G_OBJECT(imhtml));
+
 }
 
 /* Boring GTK+ stuff */
@@ -3148,6 +3173,7 @@
 	char *basename = g_path_get_basename(filename);
 	char *ext = strrchr(basename, '.');
 #endif
+	char *newfilename;
 
 	gtk_widget_destroy(image->filesel);
 	image->filesel = NULL;
@@ -3162,7 +3188,7 @@
 			gchar *fmt_ext = extensions[0];
 			const gchar* file_ext = filename + strlen(filename) - strlen(fmt_ext);
 
-			if(!strcmp(fmt_ext, file_ext)){
+			if(!g_ascii_strcasecmp(fmt_ext, file_ext)){
 				type = gdk_pixbuf_format_get_name(format);
 				break;
 			}
@@ -3195,6 +3221,7 @@
 	/* If I can't find a valid type, I will just tell the user about it and then assume
 	   it's a png */
 	if (!type){
+		char *basename, *tmp;
 #if GTK_CHECK_VERSION(2,4,0)
 		GtkWidget *dialog = gtk_message_dialog_new_with_markup(NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
 						_("<span size='larger' weight='bold'>Unrecognized file type</span>\n\nDefaulting to PNG."));
@@ -3205,10 +3232,26 @@
 
 		g_signal_connect_swapped(dialog, "response", G_CALLBACK (gtk_widget_destroy), dialog);
 		gtk_widget_show(dialog);
+
 		type = g_strdup("png");
+		basename = g_path_get_basename(filename);
+		tmp = strrchr(basename, '.');
+		if (tmp != NULL)
+			tmp[0] = '\0';
+		newfilename = g_strdup_printf("%s.png", basename);
+		g_free(basename);
+	} else {
+		/*
+		 * We're able to save the file in it's original format, so we
+		 * can use the original file name.
+		 */
+		newfilename = g_strdup(filename);
 	}
 
-	gdk_pixbuf_save(image->pixbuf, filename, type, &error, NULL);
+	gdk_pixbuf_save(image->pixbuf, newfilename, type, &error, NULL);
+
+	g_free(newfilename);
+	g_free(type);
 
 	if (error){
 #if GTK_CHECK_VERSION(2,4,0)
@@ -3222,8 +3265,6 @@
 		gtk_widget_show(dialog);
 		g_error_free(error);
 	}
-
-	g_free(type);
 }
 
 #if GTK_CHECK_VERSION(2,4,0) /* FILECHOOSER */
@@ -4432,7 +4473,9 @@
 
 	if (imhtml_smiley && imhtml_smiley->flags & GTK_IMHTML_SMILEY_CUSTOM) {
 		ebox = gtk_event_box_new();
+#if GTK_CHECK_VERSION(2,4,0)
 		gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE);
+#endif
 		gtk_widget_show(ebox);
 	}
 
--- a/pidgin/gtkimhtmltoolbar.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/gtkimhtmltoolbar.c	Mon Jun 18 01:48:35 2007 +0000
@@ -71,7 +71,9 @@
 do_small(GtkWidget *smalltb, GtkIMHtmlToolbar *toolbar)
 {
 	g_return_if_fail(toolbar != NULL);
-	gtk_imhtml_font_shrink(GTK_IMHTML(toolbar->imhtml));
+	/* Only shrink the font on activation, not deactivation as well */
+	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(smalltb)))
+		gtk_imhtml_font_shrink(GTK_IMHTML(toolbar->imhtml));
 	gtk_widget_grab_focus(toolbar->imhtml);
 }
 
@@ -79,7 +81,9 @@
 do_big(GtkWidget *large, GtkIMHtmlToolbar *toolbar)
 {
 	g_return_if_fail(toolbar);
-	gtk_imhtml_font_grow(GTK_IMHTML(toolbar->imhtml));
+	/* Only grow the font on activation, not deactivation as well */
+	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(large)))
+		gtk_imhtml_font_grow(GTK_IMHTML(toolbar->imhtml));
 	gtk_widget_grab_focus(toolbar->imhtml);
 }
 
--- a/pidgin/gtkmain.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/gtkmain.c	Mon Jun 18 01:48:35 2007 +0000
@@ -108,21 +108,19 @@
 };
 #endif
 
-static int
+static void
 dologin_named(const char *name)
 {
 	PurpleAccount *account;
 	char **names;
 	int i;
-	int ret = -1;
 
 	if (name != NULL) { /* list of names given */
 		names = g_strsplit(name, ",", 64);
 		for (i = 0; names[i] != NULL; i++) {
 			account = purple_accounts_find(names[i], NULL);
 			if (account != NULL) { /* found a user */
-				ret = 0;
-				purple_account_connect(account);
+				purple_account_set_enabled(account, PIDGIN_UI, TRUE);
 			}
 		}
 		g_strfreev(names);
@@ -133,12 +131,9 @@
 		if (accounts != NULL)
 		{
 			account = (PurpleAccount *)accounts->data;
-			ret = 0;
-			purple_account_connect(account);
+			purple_account_set_enabled(account, PIDGIN_UI, TRUE);
 		}
 	}
-
-	return ret;
 }
 
 #ifdef HAVE_SIGNAL_H
@@ -439,7 +434,6 @@
 	char *opt_config_dir_arg = NULL;
 	char *opt_login_arg = NULL;
 	char *opt_session_arg = NULL;
-	int dologin_ret = -1;
 	char *search_path;
 	GList *accounts;
 #ifdef HAVE_SIGNAL_H
@@ -473,6 +467,9 @@
 #else
 	debug_enabled = FALSE;
 #endif
+
+	/* This is the first Glib function call. Make sure to initialize GThread bfeore then */
+	g_thread_init(NULL);
 	
 #ifdef ENABLE_NLS
 	bindtextdomain(PACKAGE, LOCALEDIR);
@@ -785,14 +782,23 @@
 		pidgin_debug_window_show();
 
 	if (opt_login) {
-		dologin_ret = dologin_named(opt_login_arg);
+		/* disable all accounts */
+		for (accounts = purple_accounts_get_all(); accounts != NULL; accounts = accounts->next) {
+			PurpleAccount *account = accounts->data;
+			purple_account_set_enabled(account, PIDGIN_UI, FALSE);
+		}
+		/* honor the startup status preference */
+		if (!purple_prefs_get_bool("/purple/savedstatus/startup_current_status"))
+			purple_savedstatus_activate(purple_savedstatus_get_startup());
+		/* now enable the requested ones */
+		dologin_named(opt_login_arg);
 		if (opt_login_arg != NULL) {
 			g_free(opt_login_arg);
 			opt_login_arg = NULL;
 		}
 	}
 
-	if (opt_nologin)
+	if (opt_nologin && !opt_login)
 	{
 		/* Set all accounts to "offline" */
 		PurpleSavedStatus *saved_status;
@@ -808,7 +814,7 @@
 		/* Set the status for each account */
 		purple_savedstatus_activate(saved_status);
 	}
-	else
+	else if (!opt_login)
 	{
 		/* Everything is good to go--sign on already */
 		if (!purple_prefs_get_bool("/purple/savedstatus/startup_current_status"))
--- a/pidgin/gtknotify.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/gtknotify.c	Mon Jun 18 01:48:35 2007 +0000
@@ -40,6 +40,12 @@
 
 typedef struct
 {
+	GtkWidget *window;
+	int count;
+} PidginUserInfo;
+
+typedef struct
+{
 	PurpleAccount *account;
 	char *url;
 	GtkWidget *label;
@@ -624,7 +630,7 @@
 	gtk_widget_show(button);
 
 	g_signal_connect_swapped(G_OBJECT(button), "clicked",
-							 G_CALLBACK(formatted_close_cb), window);
+							 G_CALLBACK(gtk_widget_destroy), window);
 	g_signal_connect(G_OBJECT(window), "key_press_event",
 					 G_CALLBACK(formatted_input_cb), NULL);
 
@@ -878,6 +884,11 @@
 static void
 remove_userinfo(GtkWidget *widget, gpointer key)
 {
+	PidginUserInfo *pinfo = g_hash_table_lookup(userinfo, key);
+
+	while (pinfo->count--)
+		purple_notify_close(PURPLE_NOTIFY_USERINFO, widget);
+
 	g_hash_table_remove(userinfo, key);
 }
 
@@ -888,26 +899,33 @@
 	char *info;
 	void *ui_handle;
 	char *key = userinfo_hash(purple_connection_get_account(gc), who);
+	PidginUserInfo *pinfo = NULL;
 
 	if (!userinfo) {
-		userinfo = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+		userinfo = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
 	}
 
 	info = purple_notify_user_info_get_text_with_newline(user_info, "<br />");
-	ui_handle = g_hash_table_lookup(userinfo, key);
-	if (ui_handle != NULL) {
-		GtkIMHtml *imhtml = g_object_get_data(G_OBJECT(ui_handle), "info-widget");
+	pinfo = g_hash_table_lookup(userinfo, key);
+	if (pinfo != NULL) {
+		GtkIMHtml *imhtml = g_object_get_data(G_OBJECT(pinfo->window), "info-widget");
 		char *linked_text = purple_markup_linkify(info);
 		gtk_imhtml_clear(imhtml);
 		gtk_imhtml_append_text(imhtml, linked_text, notify_imhtml_options());
 		g_free(linked_text);
 		g_free(key);
+		ui_handle = pinfo->window;
+		pinfo->count++;
 	} else {
 		char *primary = g_strdup_printf(_("Info for %s"), who);
 		ui_handle = pidgin_notify_formatted(_("Buddy Information"), primary, NULL, info);
-		g_hash_table_insert(userinfo, key, ui_handle);
+		g_signal_handlers_disconnect_by_func(G_OBJECT(ui_handle), G_CALLBACK(formatted_close_cb), NULL);
 		g_signal_connect(G_OBJECT(ui_handle), "destroy", G_CALLBACK(remove_userinfo), key);
 		g_free(primary);
+		pinfo = g_new0(PidginUserInfo, 1);
+		pinfo->window = ui_handle;
+		pinfo->count = 1;
+		g_hash_table_insert(userinfo, key, pinfo);
 	}
 	g_free(info);
 	return ui_handle;
--- a/pidgin/gtkpounce.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/gtkpounce.c	Mon Jun 18 01:48:35 2007 +0000
@@ -783,7 +783,7 @@
 	gtk_widget_show(table);
 
 	dialog->on_away =
-		gtk_check_button_new_with_mnemonic(_("P_ounce only when my status is not available"));
+		gtk_check_button_new_with_mnemonic(_("P_ounce only when my status is not Available"));
 	gtk_table_attach(GTK_TABLE(table), dialog->on_away, 0, 1, 0, 1,
 					 GTK_FILL, 0, 0, 0);
 
--- a/pidgin/gtkprefs.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/gtkprefs.c	Mon Jun 18 01:48:35 2007 +0000
@@ -382,7 +382,7 @@
 	new_theme = current_smiley_theme;
 	description = g_strdup_printf("<span size='larger' weight='bold'>%s</span> - %s\n"
 								"<span size='smaller' foreground='white'>%s</span>",
-								new_theme->name, new_theme->author, new_theme->desc);
+								_(new_theme->name), _(new_theme->author), _(new_theme->desc));
 	gtk_list_store_set(smiley_theme_store, &iter, 1, description, -1);
 	g_free(description);
 
@@ -391,7 +391,7 @@
 		if (gtk_tree_model_get_iter(model, &iter, oldpath)) {
 			description = g_strdup_printf("<span size='larger' weight='bold'>%s</span> - %s\n"
 								"<span size='smaller' foreground='dim grey'>%s</span>",
-								old_theme->name, old_theme->author, old_theme->desc);
+								_(old_theme->name), _(old_theme->author), _(old_theme->desc));
 			gtk_list_store_set(smiley_theme_store, &iter, 1,
 				description, -1);
 			g_free(description);
@@ -426,7 +426,7 @@
 		struct smiley_theme *theme = themes->data;
 		char *description = g_strdup_printf("<span size='larger' weight='bold'>%s</span> - %s\n"
 						    "<span size='smaller' foreground='dim grey'>%s</span>",
-						    theme->name, theme->author, theme->desc);
+						    _(theme->name), _(theme->author), _(theme->desc));
 		gtk_list_store_append (smiley_theme_store, &iter);
 
 		/*
@@ -881,6 +881,15 @@
 	return ret;
 }
 
+#if GTK_CHECK_VERSION(2,4,0)
+static void
+pidgin_custom_font_set(GtkFontButton *font_button, gpointer nul)
+{
+	purple_prefs_set_string(PIDGIN_PREFS_ROOT "/conversations/custom_font",
+				gtk_font_button_get_font_name(font_button));
+}
+#endif
+
 static GtkWidget *
 conv_page()
 {
@@ -889,9 +898,17 @@
 	GtkWidget *toolbar;
 	GtkWidget *iconpref1;
 	GtkWidget *iconpref2;
+	GtkWidget *fontpref;
 	GtkWidget *imhtml;
 	GtkWidget *frame;
 
+#if GTK_CHECK_VERSION(2,4,0)
+	GtkWidget *hbox;
+	GtkWidget *label;
+	GtkWidget *font_button;
+	const char *font_name;
+#endif
+
 	ret = gtk_vbox_new(FALSE, PIDGIN_HIG_CAT_SPACE);
 	gtk_container_set_border_width(GTK_CONTAINER(ret), PIDGIN_HIG_BORDER);
 
@@ -922,6 +939,26 @@
 	pidgin_prefs_checkbox(_("F_lash window when IMs are received"), PIDGIN_PREFS_ROOT "/win32/blink_im", vbox);
 #endif
 
+#if GTK_CHECK_VERSION(2,4,0)
+	vbox = pidgin_make_frame(ret, _("Font"));
+	if (purple_running_gnome())
+		fontpref = pidgin_prefs_checkbox(_("Use document font from _theme"), PIDGIN_PREFS_ROOT "/conversations/use_theme_font", vbox);
+	else
+		fontpref = pidgin_prefs_checkbox(_("Use font from _theme"), PIDGIN_PREFS_ROOT "/conversations/use_theme_font", vbox);
+	hbox = gtk_hbox_new(FALSE, 3);
+	label = gtk_label_new_with_mnemonic(_("Conversation _font:"));
+	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+	font_name = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/custom_font");
+	font_button = gtk_font_button_new_with_font(purple_prefs_get_string(font_name ? font_name : NULL));
+	gtk_font_button_set_show_style(GTK_FONT_BUTTON(font_button), TRUE);
+	gtk_box_pack_start(GTK_BOX(hbox), font_button, FALSE, FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+	if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/use_theme_font"))
+		gtk_widget_set_sensitive(hbox, FALSE);
+	g_signal_connect(G_OBJECT(fontpref), "clicked", G_CALLBACK(pidgin_toggle_sensitive), hbox);
+	g_signal_connect(G_OBJECT(font_button), "font-set", G_CALLBACK(pidgin_custom_font_set), NULL);
+#endif
+
 	vbox = pidgin_make_frame(ret, _("Default Formatting"));
 
 	frame = pidgin_create_imhtml(TRUE, &imhtml, &toolbar, NULL);
@@ -1693,6 +1730,7 @@
 			vbox->parent->parent, TRUE, TRUE, 0, GTK_PACK_START);
 
 	sw = gtk_scrolled_window_new(NULL,NULL);
+	gtk_widget_set_size_request(sw, -1, 100);
 	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
 	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN);
 
--- a/pidgin/gtkrequest.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/gtkrequest.c	Mon Jun 18 01:48:35 2007 +0000
@@ -323,7 +323,8 @@
 	/* Setup the dialog */
 	gtk_container_set_border_width(GTK_CONTAINER(dialog), PIDGIN_HIG_BORDER/2);
 	gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER/2);
-	gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
+	if (!multiline)
+		gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
 	gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
 	gtk_dialog_set_default_response(GTK_DIALOG(dialog), 0);
 	gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog)->vbox), PIDGIN_HIG_BORDER);
@@ -341,7 +342,7 @@
 	/* Vertical box */
 	vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER);
 
-	gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
 
 	/* Descriptive label */
 	primary_esc = (primary != NULL) ? g_markup_escape_text(primary, -1) : NULL;
@@ -359,7 +360,7 @@
 	gtk_label_set_markup(GTK_LABEL(label), label_text);
 	gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
-	gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
+	gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
 
 	g_free(label_text);
 
--- a/pidgin/gtksavedstatuses.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/gtksavedstatuses.c	Mon Jun 18 01:48:35 2007 +0000
@@ -1088,7 +1088,6 @@
 	dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 	gtk_window_set_role(GTK_WINDOW(win), "status");
 	gtk_window_set_title(GTK_WINDOW(win), _("Status"));
-	gtk_window_set_resizable(GTK_WINDOW(win), FALSE);
 	gtk_container_set_border_width(GTK_CONTAINER(win), PIDGIN_HIG_BORDER);
 
 	g_signal_connect(G_OBJECT(win), "delete_event",
@@ -1137,7 +1136,7 @@
 
 	/* Status message */
 	hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
-	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
 
 	label = gtk_label_new_with_mnemonic(_("_Message:"));
 	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
--- a/pidgin/gtksound.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/gtksound.c	Mon Jun 18 01:48:35 2007 +0000
@@ -370,12 +370,12 @@
 		break;
 	case GST_MESSAGE_ERROR:
 		gst_message_parse_error(msg, &err, NULL);
-		purple_debug_error("gstreamer", err->message);
+		purple_debug_error("gstreamer", "%s\n", err->message);
 		g_error_free(err);
 		break;
 	case GST_MESSAGE_WARNING:
 		gst_message_parse_warning(msg, &err, NULL);
-		purple_debug_warning("gstreamer", err->message);
+		purple_debug_warning("gstreamer", "%s\n", err->message);
 		g_error_free(err);
 		break;
 	default:
--- a/pidgin/gtkstatusbox.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/gtkstatusbox.c	Mon Jun 18 01:48:35 2007 +0000
@@ -2029,6 +2029,10 @@
 	int w, h;
 	GtkIconSize icon_size = gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_MEDIUM);
 	gtk_icon_size_lookup(icon_size, &w, &h);
+	if (height > width)
+		w = width * h  / height;
+	else if (width > height)
+		h = height * w / width;
 	gdk_pixbuf_loader_set_size(loader, w, h);
 #endif
 }
--- a/pidgin/gtkthemes.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/gtkthemes.c	Mon Jun 18 01:48:35 2007 +0000
@@ -146,11 +146,14 @@
 				list->next = child;
 			else
 				theme->list = child;
+			/* Reverse the Smiley list since it was built in reverse order for efficiency reasons */
+			if (list != NULL)
+				list->smileys = g_slist_reverse(list->smileys);
 			list = child;
 		} else if (!g_ascii_strncasecmp(i, "Name=", strlen("Name="))) {
 			int len;
 			g_free(theme->name);
-			theme->name = g_strdup(i+ strlen("Name="));
+			theme->name = g_strdup(i + strlen("Name="));
 			len = strlen(theme->name);
 			theme->name[len-1] = 0;
 			if(len > 2 && theme->name[len-2] == '\r')
@@ -201,14 +204,16 @@
 
 			}
 
-			/* Reverse the Smiley list since it was built in reverse order for efficiency reasons */
-			list->smileys = g_slist_reverse(list->smileys);
 
 			if (!have_used_sfile)
 				g_free(sfile);
 		}
 	}
 
+	/* Reverse the Smiley list since it was built in reverse order for efficiency reasons */
+	if (list != NULL)
+		list->smileys = g_slist_reverse(list->smileys);
+
 	g_free(dirname);
 	fclose(f);
 
--- a/pidgin/gtkutils.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/gtkutils.c	Mon Jun 18 01:48:35 2007 +0000
@@ -61,6 +61,11 @@
 #include "gtkthemes.h"
 #include "gtkutils.h"
 
+typedef struct {
+	GtkWidget *menu;
+	gint default_item;
+} AopMenu;
+
 static guint accels_save_timer = 0;
 
 static gboolean
@@ -89,6 +94,7 @@
 void
 pidgin_setup_imhtml(GtkWidget *imhtml)
 {
+	PangoFontDescription *desc = NULL;
 	g_return_if_fail(imhtml != NULL);
 	g_return_if_fail(GTK_IS_IMHTML(imhtml));
 
@@ -99,10 +105,12 @@
 
 	gtk_imhtml_set_funcs(GTK_IMHTML(imhtml), &gtkimhtml_cbs);
 
-	/* Use the GNOME "document" font, if applicable */
-	if (purple_running_gnome()) {
+	if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/use_theme_font")) {
+		const char *font = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/custom_font");
+		desc = pango_font_description_from_string(font);
+	} else if (purple_running_gnome()) {
+		/* Use the GNOME "document" font, if applicable */
 		char *path, *font;
-		PangoFontDescription *desc = NULL;
 
 		if ((path = g_find_program_in_path("gconftool-2"))) {
 			g_free(path);
@@ -113,11 +121,11 @@
 		}
 		desc = pango_font_description_from_string(font);
 		g_free(font);
-
-		if (desc) {
-			gtk_widget_modify_font(imhtml, desc);
-			pango_font_description_free(desc);
-		}
+	}
+	
+	if (desc) {
+		gtk_widget_modify_font(imhtml, desc);
+		pango_font_description_free(desc);
 	}
 }
 
@@ -430,101 +438,160 @@
 	return vbox;
 }
 
+static gpointer
+aop_option_menu_get_selected(GtkWidget *optmenu, GtkWidget **p_item)
+{
+	GtkWidget *menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu));
+	GtkWidget *item = gtk_menu_get_active(GTK_MENU(menu));
+	if (p_item)
+		(*p_item) = item;
+	return g_object_get_data(G_OBJECT(item), "aop_per_item_data");
+}
+
 static void
-protocol_menu_cb(GtkWidget *optmenu, GCallback cb)
+aop_menu_cb(GtkWidget *optmenu, GCallback cb)
 {
-	GtkWidget *menu;
 	GtkWidget *item;
-	const char *protocol;
-	gpointer user_data;
-
-	menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu));
-	item = gtk_menu_get_active(GTK_MENU(menu));
-
-	protocol = g_object_get_data(G_OBJECT(item), "protocol");
-
-	if (!strcmp(protocol, "prpl-fake"))
-		protocol = g_object_get_data(G_OBJECT(item), "real_protocol");
-
-	if (!strcmp(protocol, g_object_get_data(G_OBJECT(optmenu), "last_protocol")))
-		return;
-
-	user_data = (g_object_get_data(G_OBJECT(optmenu), "user_data"));
-	g_object_set_data(G_OBJECT(optmenu), "last_protocol", (gpointer)protocol);
-
-	if (cb != NULL)
-		((void (*)(GtkWidget *, const char *, gpointer))cb)(item, protocol,
-															user_data);
+	gpointer per_item_data;
+
+	per_item_data = aop_option_menu_get_selected(optmenu, &item);
+
+	if (cb != NULL) {
+		((void (*)(GtkWidget *, gpointer, gpointer))cb)(item, per_item_data, g_object_get_data(G_OBJECT(optmenu), "user_data"));
+	}
 }
 
 static GtkWidget *
-pidgin_protocol_option_menu_item(GtkWidget *menu, GtkSizeGroup *sg, GtkWidget *image,
-                                  const char *name, const char *id)
+aop_menu_item_new(GtkSizeGroup *sg, GdkPixbuf *pixbuf, const char *lbl, gpointer per_item_data)
 {
 	GtkWidget *item;
 	GtkWidget *hbox;
+	GtkWidget *image;
 	GtkWidget *label;
 
-	/* Create the item. */
 	item = gtk_menu_item_new();
-
-	/* Create the hbox. */
+	gtk_widget_show(item);
+
 	hbox = gtk_hbox_new(FALSE, 4);
-	gtk_container_add(GTK_CONTAINER(item), hbox);
 	gtk_widget_show(hbox);
 
-	gtk_size_group_add_widget(sg, image);
-
-	gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
+	/* Create the image */
+	if (pixbuf == NULL)
+		image = gtk_image_new();
+	else
+		image = gtk_image_new_from_pixbuf(pixbuf);
 	gtk_widget_show(image);
 
-	/* Create the label. */
-	label = gtk_label_new(name);
+	if (sg)
+		gtk_size_group_add_widget(sg, image);
+
+	/* Create the label */
+	label = gtk_label_new (lbl);
+	gtk_widget_show (label);
 	gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
-	gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+	gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
+	
+	gtk_container_add(GTK_CONTAINER(item), hbox);
+	gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
 	gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
-	gtk_widget_show(label);
-
-	g_object_set_data(G_OBJECT(item), "protocol", (gpointer)id);
-
-	gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
-	gtk_widget_show(item);
-	pidgin_set_accessible_label (item, label);
+
+	g_object_set_data(G_OBJECT (item), "aop_per_item_data", per_item_data);
+
+	pidgin_set_accessible_label(item, label);
 
 	return item;
 }
 
-GtkWidget *
-pidgin_protocol_option_menu_new(const char *id, GCallback cb,
-								  gpointer user_data)
+static GtkWidget *
+aop_option_menu_new(AopMenu *aop_menu, GCallback cb, gpointer user_data)
+{
+	GtkWidget *optmenu;
+
+	optmenu = gtk_option_menu_new();
+	gtk_widget_show(optmenu);
+	gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), aop_menu->menu);
+
+	if (aop_menu->default_item != -1)
+		gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), aop_menu->default_item);
+
+	g_object_set_data_full(G_OBJECT(optmenu), "aop_menu", aop_menu, (GDestroyNotify)g_free);
+	g_object_set_data(G_OBJECT(optmenu), "user_data", user_data);
+
+	g_signal_connect(G_OBJECT(optmenu), "changed", G_CALLBACK(aop_menu_cb), cb);
+
+	return optmenu;
+}
+
+static void
+aop_option_menu_replace_menu(GtkWidget *optmenu, AopMenu *new_aop_menu)
+{
+	if (gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu)))
+		gtk_option_menu_remove_menu(GTK_OPTION_MENU(optmenu));
+
+	gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), new_aop_menu->menu);
+
+	if (new_aop_menu->default_item != -1)
+		gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), new_aop_menu->default_item);
+
+	g_object_set_data_full(G_OBJECT(optmenu), "aop_menu", new_aop_menu, (GDestroyNotify)g_free);
+}
+
+static void
+aop_option_menu_select_by_data(GtkWidget *optmenu, gpointer data)
 {
+	guint idx;
+	GList *llItr = NULL;
+
+	for (idx = 0, llItr = GTK_MENU_SHELL(gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu)))->children;
+	     llItr != NULL;
+	     llItr = llItr->next, idx++) {
+		if (data == g_object_get_data(G_OBJECT(llItr->data), "aop_per_item_data")) {
+			gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), idx);
+			break;
+		}
+	}
+}
+
+static GdkPixbuf *
+get_prpl_pixbuf(PurplePluginProtocolInfo *prpl_info)
+{
+	const char *proto_name;
+	GdkPixbuf *pixbuf = NULL;
+	char *filename;
+	char buf[256];
+
+	proto_name = prpl_info->list_icon(NULL, NULL);
+	g_return_val_if_fail(proto_name != NULL, NULL);
+
+	g_snprintf(buf, sizeof(buf), "%s.png", proto_name);
+	filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "16", buf, NULL);
+	pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
+	g_free(filename);
+
+	return pixbuf;
+}
+
+static AopMenu *
+create_protocols_menu(const char *default_proto_id)
+{
+	AopMenu *aop_menu = NULL;
 	PurplePluginProtocolInfo *prpl_info;
 	PurplePlugin *plugin;
-	GtkWidget *optmenu;
-	GtkWidget *menu;
-	GdkPixbuf *pixbuf;
-	GtkWidget *image;
-	GList *p;
+	GdkPixbuf *pixbuf = NULL;
 	GtkSizeGroup *sg;
-	char *filename;
-	const char *proto_name;
-	char buf[256];
-	int i, selected_index = -1;
+	GList *p;
 	const char *gtalk_name = NULL;
+	int i;
+
+	aop_menu = g_malloc0(sizeof(AopMenu));
+	aop_menu->default_item = -1;
+	aop_menu->menu = gtk_menu_new();
+	gtk_widget_show(aop_menu->menu);
+	sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
 
 	if (purple_find_prpl("prpl-jabber"))
 		gtalk_name = _("Google Talk");
 
-	optmenu = gtk_option_menu_new();
-	gtk_widget_show(optmenu);
-
-	g_object_set_data(G_OBJECT(optmenu), "user_data", user_data);
-
-	menu = gtk_menu_new();
-	gtk_widget_show(menu);
-
-	sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
-
 	for (p = purple_plugins_get_protocols(), i = 0;
 		 p != NULL;
 		 p = p->next, i++) {
@@ -532,126 +599,74 @@
 		plugin = (PurplePlugin *)p->data;
 		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
 
-		if (gtalk_name && strcmp(gtalk_name, plugin->info->name) < 0)
-		{
-			GtkWidget *gtalk_item;
-
-			filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols",
-			                            "16", "google-talk.png", NULL);
+		if (gtalk_name && strcmp(gtalk_name, plugin->info->name) < 0) {
+			char *filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols",
+			                                  "16", "google-talk.png", NULL);
 			pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
 			g_free(filename);
 
+			gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
+				aop_menu_item_new(sg, pixbuf, gtalk_name, "prpl-jabber"));
 
 			if (pixbuf)
-				image = gtk_image_new_from_pixbuf(pixbuf);
-			else
-				image = gtk_image_new();
-
-			gtalk_item = pidgin_protocol_option_menu_item(menu, sg, image, gtalk_name, "prpl-fake");
-			g_object_set_data(G_OBJECT(gtalk_item), "real_protocol", "prpl-jabber");
-			i++;
+				g_object_unref(pixbuf);
 
 			gtalk_name = NULL;
+			i++;
 		}
 
-		/* Load the image. */
-		proto_name = prpl_info->list_icon(NULL, NULL);
-		g_snprintf(buf, sizeof(buf), "%s.png", proto_name);
-
-		filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols",
-									"16", buf, NULL);
-		pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
-		g_free(filename);
+		pixbuf = get_prpl_pixbuf(prpl_info);
+
+		gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
+			aop_menu_item_new(sg, pixbuf, plugin->info->name, plugin->info->id));
 
 		if (pixbuf)
-			image = gtk_image_new_from_pixbuf(pixbuf);
-		else
-			image = gtk_image_new();
-
-		pidgin_protocol_option_menu_item(menu, sg, image, plugin->info->name, plugin->info->id);
-
-		if (id != NULL && !strcmp(plugin->info->id, id))
-		{
-			g_object_set_data(G_OBJECT(optmenu), "last_protocol", plugin->info->id);
-			selected_index = i;
-		}
-		else if (i == 0)
-		{
-			/* Ensure we set the protocol even if id is NULL or can't be found. */
-			g_object_set_data(G_OBJECT(optmenu), "last_protocol", plugin->info->id);
-		}
-
-		if (pixbuf)
-			g_object_unref(G_OBJECT(pixbuf));
+			g_object_unref(pixbuf);
+
+		if (default_proto_id != NULL && !strcmp(plugin->info->id, default_proto_id))
+			aop_menu->default_item = i;
 	}
 
-	gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), menu);
-
-	if (selected_index != -1)
-		gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), selected_index);
-
-	g_signal_connect(G_OBJECT(optmenu), "changed",
-					 G_CALLBACK(protocol_menu_cb), cb);
-
 	g_object_unref(sg);
 
-	return optmenu;
+	return aop_menu;
+}
+
+GtkWidget *
+pidgin_protocol_option_menu_new(const char *id, GCallback cb,
+								  gpointer user_data)
+{
+	return aop_option_menu_new(create_protocols_menu(id), cb, user_data);
 }
 
 PurpleAccount *
 pidgin_account_option_menu_get_selected(GtkWidget *optmenu)
 {
-	GtkWidget *menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu));
-	GtkWidget *item = gtk_menu_get_active(GTK_MENU(menu));
-	return g_object_get_data(G_OBJECT(item), "account");
+	return (PurpleAccount *)aop_option_menu_get_selected(optmenu, NULL);
 }
 
-static void
-account_menu_cb(GtkWidget *optmenu, GCallback cb)
-{
-	GtkWidget *menu;
-	GtkWidget *item;
-	PurpleAccount *account;
-	gpointer user_data;
-
-	menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu));
-	item = gtk_menu_get_active(GTK_MENU(menu));
-
-	account   = g_object_get_data(G_OBJECT(item),    "account");
-	user_data = g_object_get_data(G_OBJECT(optmenu), "user_data");
-
-	if (cb != NULL)
-		((void (*)(GtkWidget *, PurpleAccount *, gpointer))cb)(item, account,
-															 user_data);
-}
-
-static void
-create_account_menu(GtkWidget *optmenu, PurpleAccount *default_account,
+static AopMenu *
+create_account_menu(PurpleAccount *default_account,
 					PurpleFilterAccountFunc filter_func, gboolean show_all)
 {
+	AopMenu *aop_menu = NULL;
 	PurpleAccount *account;
-	GtkWidget *menu;
-	GtkWidget *item;
-	GtkWidget *image;
-	GtkWidget *hbox;
-	GtkWidget *label;
-	GdkPixbuf *pixbuf;
+	GdkPixbuf *pixbuf = NULL;
 	GList *list;
 	GList *p;
 	GtkSizeGroup *sg;
-	char *filename;
-	const char *proto_name;
+	int i;
 	char buf[256];
-	int i, selected_index = -1;
 
 	if (show_all)
 		list = purple_accounts_get_all();
 	else
 		list = purple_connections_get_all();
 
-	menu = gtk_menu_new();
-	gtk_widget_show(menu);
-
+	aop_menu = g_malloc0(sizeof(AopMenu));
+	aop_menu->default_item = -1;
+	aop_menu->menu = gtk_menu_new();
+	gtk_widget_show(aop_menu->menu);
 	sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
 
 	for (p = list, i = 0; p != NULL; p = p->next, i++) {
@@ -673,46 +688,19 @@
 
 		plugin = purple_find_prpl(purple_account_get_protocol_id(account));
 
-		if (plugin != NULL)
+		if (plugin)
 			prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
 
-		/* Create the item. */
-		item = gtk_menu_item_new();
-
-		/* Create the hbox. */
-		hbox = gtk_hbox_new(FALSE, 4);
-		gtk_container_add(GTK_CONTAINER(item), hbox);
-		gtk_widget_show(hbox);
-
 		/* Load the image. */
-		if (prpl_info != NULL) {
-			proto_name = prpl_info->list_icon(account, NULL);
-			g_snprintf(buf, sizeof(buf), "%s.png", proto_name);
-
-			filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols",
-			                            "16", buf, NULL);
-			pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
-			g_free(filename);
-
-			if (pixbuf != NULL) {
+		if (prpl_info) {
+			pixbuf = get_prpl_pixbuf(prpl_info);
+
+			if (pixbuf) {
 				if (purple_account_is_disconnected(account) && show_all &&
 						purple_connections_get_all())
 					gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE);
-
-				image = gtk_image_new_from_pixbuf(pixbuf);
-
-				g_object_unref(G_OBJECT(pixbuf));
 			}
-			else
-				image = gtk_image_new();
 		}
-		else
-			image = gtk_image_new();
-
-		gtk_size_group_add_widget(sg, image);
-
-		gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
-		gtk_widget_show(image);
 
 		if (purple_account_get_alias(account)) {
 			g_snprintf(buf, sizeof(buf), "%s (%s) (%s)",
@@ -725,54 +713,33 @@
 					   purple_account_get_protocol_name(account));
 		}
 
-		/* Create the label. */
-		label = gtk_label_new(buf);
-		gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
-		gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
-		gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
-		gtk_widget_show(label);
-
-		g_object_set_data(G_OBJECT(item), "account", account);
-
-		gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
-		gtk_widget_show(item);
-		pidgin_set_accessible_label (item, label);
-
-		if (default_account != NULL && account == default_account)
-			selected_index = i;
+		gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
+			aop_menu_item_new(sg, pixbuf, buf, account));
+
+		if (pixbuf)
+			g_object_unref(pixbuf);
+
+		if (default_account && account == default_account)
+			aop_menu->default_item = i;
 	}
 
 	g_object_unref(sg);
 
-	gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), menu);
-
-	/* Set the place we should be at. */
-	if (selected_index != -1)
-		gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), selected_index);
+	return aop_menu;
 }
 
 static void
 regenerate_account_menu(GtkWidget *optmenu)
 {
-	GtkWidget *menu;
-	GtkWidget *item;
 	gboolean show_all;
 	PurpleAccount *account;
 	PurpleFilterAccountFunc filter_func;
 
-	menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu));
-	item = gtk_menu_get_active(GTK_MENU(menu));
-	account = g_object_get_data(G_OBJECT(item), "account");
-
-	show_all = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(optmenu),
-												 "show_all"));
-
-	filter_func = g_object_get_data(G_OBJECT(optmenu),
-										   "filter_func");
-
-	gtk_option_menu_remove_menu(GTK_OPTION_MENU(optmenu));
-
-	create_account_menu(optmenu, account, filter_func, show_all);
+	account = (PurpleAccount *)aop_option_menu_get_selected(optmenu, NULL);
+	show_all = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(optmenu), "show_all"));
+	filter_func = g_object_get_data(G_OBJECT(optmenu), "filter_func");
+
+	aop_option_menu_replace_menu(optmenu, create_account_menu(account, filter_func, show_all));
 }
 
 static void
@@ -799,28 +766,7 @@
 void
 pidgin_account_option_menu_set_selected(GtkWidget *optmenu, PurpleAccount *account)
 {
-	GtkWidget *menu;
-	GtkWidget *item;
-	gboolean show_all;
-	PurpleAccount *curaccount;
-	PurpleFilterAccountFunc filter_func;
-
-	menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu));
-	item = gtk_menu_get_active(GTK_MENU(menu));
-	curaccount = g_object_get_data(G_OBJECT(item), "account");
-
-	if (account == curaccount)
-		return;
-
-	show_all = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(optmenu),
-												 "show_all"));
-
-	filter_func = g_object_get_data(G_OBJECT(optmenu),
-										   "filter_func");
-
-	gtk_option_menu_remove_menu(GTK_OPTION_MENU(optmenu));
-
-	create_account_menu(optmenu, account, filter_func, show_all);
+	aop_option_menu_select_by_data(optmenu, account);
 }
 
 GtkWidget *
@@ -832,8 +778,7 @@
 	GtkWidget *optmenu;
 
 	/* Create the option menu */
-	optmenu = gtk_option_menu_new();
-	gtk_widget_show(optmenu);
+	optmenu = aop_option_menu_new(create_account_menu(default_account, filter_func, show_all), cb, user_data);
 
 	g_signal_connect(G_OBJECT(optmenu), "destroy",
 					 G_CALLBACK(account_menu_destroyed_cb), NULL);
@@ -855,15 +800,7 @@
 	/* Set some data. */
 	g_object_set_data(G_OBJECT(optmenu), "user_data", user_data);
 	g_object_set_data(G_OBJECT(optmenu), "show_all", GINT_TO_POINTER(show_all));
-	g_object_set_data(G_OBJECT(optmenu), "filter_func",
-					  filter_func);
-
-	/* Create and set the actual menu. */
-	create_account_menu(optmenu, default_account, filter_func, show_all);
-
-	/* And now the last callback. */
-	g_signal_connect(G_OBJECT(optmenu), "changed",
-					 G_CALLBACK(account_menu_cb), cb);
+	g_object_set_data(G_OBJECT(optmenu), "filter_func", filter_func);
 
 	return optmenu;
 }
@@ -1521,8 +1458,7 @@
 			else
 				purple_request_choice(NULL, NULL,
 						    _("You have dragged an image"),
-						    (ft ? _("You can send this image as a file transfer or "
-							   "embed it into this message, or use it as the buddy icon for this user.") :
+						    (ft ? _("You can send this image as a file transfer, or use it as the buddy icon for this user.") :
 						    _("You can insert this image into this message, or use it as the buddy icon for this user")),
 						    (ft ? DND_FILE_TRANSFER : DND_IM_IMAGE),
 							"OK", (GCallback)dnd_image_ok_callback,
@@ -1903,21 +1839,8 @@
 	if (account == NULL)
 		return TRUE;
 
-	if (optmenu != NULL) {
-		GList *items;
-		guint index = 0;
-		pidgin_account_option_menu_set_selected(optmenu, account);
-		items = GTK_MENU_SHELL(gtk_option_menu_get_menu(GTK_OPTION_MENU(optmenu)))->children;
-
-		do {
-			if (account == g_object_get_data(G_OBJECT(items->data), "account")) {
-				/* Set the account in the GUI. */
-				gtk_option_menu_set_history(GTK_OPTION_MENU(optmenu), index);
-				return TRUE;
-			}
-			index++;
-		} while ((items = items->next) != NULL);
-	}
+	if (optmenu != NULL)
+		aop_option_menu_select_by_data(optmenu, account);
 
 	return TRUE;
 }
@@ -2115,6 +2038,7 @@
 static void
 screenname_autocomplete_destroyed_cb(GtkWidget *widget, gpointer data)
 {
+	g_free(data);
 	purple_signals_disconnect_by_handle(widget);
 }
 
@@ -2196,7 +2120,7 @@
 	purple_signal_connect(purple_accounts_get_handle(), "account-removed", entry,
 						PURPLE_CALLBACK(repopulate_autocomplete), cb_data);
 
-	g_signal_connect(G_OBJECT(entry), "destroy", G_CALLBACK(screenname_autocomplete_destroyed_cb), NULL);
+	g_signal_connect(G_OBJECT(entry), "destroy", G_CALLBACK(screenname_autocomplete_destroyed_cb), data);
 }
 
 void pidgin_set_cursor(GtkWidget *widget, GdkCursorType cursor_type)
@@ -3111,20 +3035,20 @@
 
         row = pixels;
         for (i = 3; i < rowstride; i+=4) {
-                if (row[i] != 0xff)
+                if (row[i] < 0xfe)
                         return FALSE;
         }
 
         for (i = 1; i < height - 1; i++) {
                 row = pixels + (i*rowstride);
-                if (row[3] != 0xff || row[rowstride-1] != 0xff) {
+                if (row[3] < 0xfe || row[rowstride-1] < 0xfe) {
                         return FALSE;
-                }
+            }
         }
 
         row = pixels + ((height-1) * rowstride);
         for (i = 3; i < rowstride; i+=4) {
-                if (row[i] != 0xff)
+                if (row[i] < 0xfe)
                         return FALSE;
         }
 
--- a/pidgin/pidginstock.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pidginstock.c	Mon Jun 18 01:48:35 2007 +0000
@@ -109,7 +109,7 @@
 	{ PIDGIN_STOCK_STATUS_XA, 	"status", "extended-away.png",	TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, PIDGIN_STOCK_STATUS_XA_I },
 	{ PIDGIN_STOCK_STATUS_LOGIN, 	"status", "log-in.png",		TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL },
 	{ PIDGIN_STOCK_STATUS_LOGOUT, 	"status", "log-out.png",	TRUE, TRUE, TRUE, TRUE, FALSE, FALSE , NULL },
-	{ PIDGIN_STOCK_STATUS_OFFLINE, 	"status", "offline.png",	TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL  },
+	{ PIDGIN_STOCK_STATUS_OFFLINE, 	"status", "offline.png",	TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, PIDGIN_STOCK_STATUS_OFFLINE_I  },
 	{ PIDGIN_STOCK_STATUS_PERSON, 	"status", "person.png",		TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL  },
 	{ PIDGIN_STOCK_STATUS_MESSAGE, 	"status", "message-pending.png",TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL  },
 	
@@ -161,14 +161,17 @@
 	{ PIDGIN_STOCK_TOOLBAR_SELECT_AVATAR, "toolbar", "select-avatar.png", FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, NULL  },
 	{ PIDGIN_STOCK_TOOLBAR_SEND_FILE, "toolbar", "send-file.png", TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL  },
 
-	{ PIDGIN_STOCK_TRAY_AVAILABLE, "tray", "tray-online.png", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, NULL  },
-	{ PIDGIN_STOCK_TRAY_INVISIBLE, "tray", "tray-invisible.png", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, NULL  },
-	{ PIDGIN_STOCK_TRAY_AWAY, "tray", "tray-away.png", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, NULL  },
-	{ PIDGIN_STOCK_TRAY_BUSY, "tray", "tray-busy.png", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, NULL  },
-	{ PIDGIN_STOCK_TRAY_XA, "tray", "tray-extended-away.png", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, NULL  },
-	{ PIDGIN_STOCK_TRAY_OFFLINE, "tray", "tray-offline.png", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, NULL  },
-	{ PIDGIN_STOCK_TRAY_CONNECT, "tray", "tray-connecting.png", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, NULL  },
-	{ PIDGIN_STOCK_TRAY_PENDING, "tray", "tray-message.png", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, NULL  }
+	{ PIDGIN_STOCK_TRAY_AVAILABLE, "tray", "tray-online.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL  },
+	{ PIDGIN_STOCK_TRAY_INVISIBLE, "tray", "tray-invisible.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL  },
+	{ PIDGIN_STOCK_TRAY_AWAY, "tray", "tray-away.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL  },
+	{ PIDGIN_STOCK_TRAY_BUSY, "tray", "tray-busy.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL  },
+	{ PIDGIN_STOCK_TRAY_XA, "tray", "tray-extended-away.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL  },
+	{ PIDGIN_STOCK_TRAY_OFFLINE, "tray", "tray-offline.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL  },
+	{ PIDGIN_STOCK_TRAY_CONNECT, "tray", "tray-connecting.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL  },
+	{ PIDGIN_STOCK_TRAY_PENDING, "tray", "tray-new-im.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL  }
+/* Uncomment me after 2.0.2!
+ *	{ PIDGIN_STOCK_TRAY_EMAIL, "tray", "tray-message.png", TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, NULL  }
+ */
 };
 
 static gchar *
--- a/pidgin/pidginstock.h	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pidginstock.h	Mon Jun 18 01:48:35 2007 +0000
@@ -70,6 +70,7 @@
 #define PIDGIN_STOCK_STATUS_LOGIN      "pidgin-status-login"
 #define PIDGIN_STOCK_STATUS_LOGOUT     "pidgin-status-logout"
 #define PIDGIN_STOCK_STATUS_OFFLINE    "pidgin-status-offline"
+#define PIDGIN_STOCK_STATUS_OFFLINE_I  "pidgin-status-offline"
 #define PIDGIN_STOCK_STATUS_PERSON     "pidgin-status-person"
 #define PIDGIN_STOCK_STATUS_MESSAGE    "pidgin-status-message"
 
@@ -135,6 +136,9 @@
 #define PIDGIN_STOCK_TRAY_OFFLINE         "pidgin-tray-offline"
 #define PIDGIN_STOCK_TRAY_CONNECT         "pidgin-tray-connect"
 #define PIDGIN_STOCK_TRAY_PENDING         "pidgin-tray-pending"
+/* Uncomment me after 2.0.2! 
+ * #define PIDGIN_STOCK_TRAY_EMAIL		  "pidgin-tray-email"
+ */
 
 
 /*@}*/
--- a/pidgin/pixmaps/emotes/default/22/Makefile.am	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/emotes/default/22/Makefile.am	Mon Jun 18 01:48:35 2007 +0000
@@ -173,8 +173,15 @@
 		yin-yang.png
 
 pidginsmileypixdir = $(datadir)/pixmaps/pidgin/emotes/default
+pidginsmileypix_in_files = default.theme.in
 pidginsmileypix_DATA = \
         $(SMILEYS) \
         theme
 
-EXTRA_DIST = $(pidginsmileypix_DATA)
+theme: default.theme.in
+	sed -e 's/^_Name=/Name=/' \
+	    -e 's/^_Description=/Description=/' \
+	    -e 's/^_Author=/Author=/' \
+	$< > $@
+
+EXTRA_DIST = $(pidginsmileypix_DATA) $(pidginsmileypix_in_files)
--- a/pidgin/pixmaps/emotes/default/22/Makefile.mingw	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/emotes/default/22/Makefile.mingw	Mon Jun 18 01:48:35 2007 +0000
@@ -10,11 +10,13 @@
 datadir = $(PIDGIN_INSTALL_DIR)
 include ./Makefile.am
 
-.PHONY: install
+.PHONY: install clean
 
-install:
+install: theme
 	if test '$(pidginsmileypix_DATA)'; then \
 	  mkdir -p $(pidginsmileypixdir); \
 	  cp $(pidginsmileypix_DATA) $(pidginsmileypixdir); \
 	fi;
 
+clean:
+	rm -f theme
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pixmaps/emotes/default/22/default.theme.in	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,357 @@
+_Name=Default
+_Description=Pidgin smileys
+Icon=smile.png
+Author=Hylke Bons
+
+# default smileys
+[default]
+smile.png           :)      :-)
+smile-big.png       :-D     :-d     :D      :d
+sad.png             :-(     :(
+wink.png            ;-)     ;)
+tongue.png          :P      :-P     :-p     :p
+shock.png           =-O     =-o
+kiss.png            :-*
+glasses-cool.png    8-)
+embarrassed.png     :-[
+crying.png          :'(
+thinking.png        :-/     :-\\
+angel.png           O:-)    o:-)
+shut-mouth.png      :-X
+moneymouth.png      :-$
+foot-in-mouth.png   :-!
+shout.png           >:o     >:O
+! skywalker.png     C:-)    c:-)    C:)     c:)
+! monkey.png        :-(|)
+
+### Following AIM 6.1
+[AIM]
+smile.png           :-)     :)
+wink.png            ;-)     ;)
+sad.png             :-(     :(
+tongue.png          :-P     :P
+shock.png           =-O
+kiss.png            :-*
+shout.png           >:o
+smile-big.png       :-D     :D
+moneymouth.png      :-$
+foot-in-mouth.png   :-!
+embarrassed.png     :-[
+angel.png           O:-)
+thinking.png        :-\\    :-/
+crying.png          :'(
+shut-mouth.png      :-X
+glasses-cool.png    8-)
+! skywalker.png     C:-)    c:-)    C:)     c:)
+! monkey.png        :-(|)
+
+### Following Windows Live Messenger 8.1
+[MSN]
+smile.png           :)      :-)
+smile-big.png       :D      :d :-D :-d
+wink.png            ;)      ;-)
+shock.png           :-O     :-o :O :o
+tongue.png          :P      :p :-P :-p
+glasses-cool.png    (H)     (h)
+angry.png           :@      :-@
+embarrassed.png     :$      :-$
+confused.png        :S      :s :-S :-s
+sad.png             :(      :-(
+crying.png          :'(
+neutral.png         :|      :-|
+devil.png           (6)
+angel.png           (A)     (a)
+love.png            (L)     (l)
+love-over.png       (U)     (u)
+msn.png             (M)     (m)
+cat.png             (@)
+dog.png             (&)
+moon.png            (S)
+star.png            (*)
+film.png            (~)
+musical-note.png    (8)
+mail.png            (E)     (e)
+rose.png            (F)     (f)
+rose-dead.png       (W)     (w)
+clock.png           (O)     (o)
+kiss.png            (K)     (k)
+present.png         (G)     (g)
+cake.png            (^)
+camera.png          (P)     (p)
+lamp.png            (I)     (i)
+coffee.png          (C)     (c)
+phone.png           (T)     (t)
+hug-left.png        ({)
+hug-right.png       (})
+beer.png            (B)     (b)
+drink.png           (D)     (d)
+boy.png             (Z)     (z)
+girl.png            (X)     (x)
+good.png            (Y)     (y)
+bad.png             (N)     (n)
+vampire.png         :[      :-[
+goat.png            (nah)
+sun.png             (#)
+rainbow.png         (R)     (r)
+quiet.png           :-#
+teeth.png           8o|
+glasses-nerdy.png   8-|
+sarcastic.png       ^o)
+secret.png          :-*
+sick.png            +o(
+snail.png           (sn)
+turtle.png          (tu)
+plate.png           (pl)
+bowl.png            (||)
+pizza.png           (pi)
+soccerball.png      (so)
+car.png             (au)
+airplane.png        (ap)
+umbrella.png        (um)
+island.png          (ip)
+computer.png        (co)
+mobile.png          (mp)
+brb.png             (brb)
+rain.png            (st)
+highfive.png        (h5)
+coins.png           (mo)
+sheep.png           (bah)
+dont-know.png       :^)
+thinking.png        *-)
+thunder.png         (li)
+party.png           <:o)
+eyeroll.png         8-)
+yawn.png            |-) 
+! skywalker.png     C:-)    c:-)    C:)     c:)
+! monkey.png        :-(|)
+
+### Hidden MSN emotes
+sigarette.png      	(ci)    (CI)
+handcuffs.png       (%)
+console.png			(xx)    (XX)
+fingers-crossed.png	(yn)    (YN)
+
+### Following QQ 2006
+[QQ]
+shock.png           /惊讶   /:O      /jy       /surprised
+curl-lip.png        /撇嘴   /:~      /pz       /curl_lip
+desire.png          /色     /:*      /se       /desire
+dazed.png           /发呆   /:|      /dazed
+party.png           /得意   /8-)     /dy       /revel
+crying.png          /流泪   /:<      /ll       /cry
+bashful.png         /害羞   /:$      /hx       /bashful
+shut-mouth.png      /闭嘴   /:X      /bz       /shut_mouth
+sleepy.png          /睡     /:Z      /shui     /sleep
+weep.png            /大哭   /:'(     /dk       /weep
+embarrassed.png     /尴尬   /:-|     /gg       /embarassed
+pissed-off.png      /发怒   /:@      /fn       /pissed_off
+act-up.png          /调皮   /:P      /tp       /act_up
+smile-big.png       /呲牙   /:D      /cy       /toothy_smile
+smile.png           /微笑   /:)      /wx       /small_smile
+sad.png             /难过   /:(      /ng       /sad
+glasses-cool.png    /酷     /:+      /kuk      /cool
+doctor.png          /非典   /:#      /feid     /SARS
+silly.png           /抓狂   /:Q      /zk       /crazy
+sick.png            /吐     /:T      /tu       /vomit
+snicker.png         /偷笑   /;p      /tx       /titter
+cute.png            /可爱   /;-D     /ka       /cute
+disdain.png         /白眼   /;d      /by       /disdain
+arrogant.png        /傲慢   /;o      /am       /arrogant
+starving.png        /饥饿   /:g      /jie      /starving
+yawn.png            /困     /|-)     /kun      /sleepy
+terror.png          /惊恐   /:!      /jk       /terror
+sweat.png           /流汗   /:L      /sweat
+smirk.png           /憨笑   /:>      /hanx     /smirk
+soldier.png         /大兵   /:;      /db       /soldier
+struggle.png        /奋斗   /;f      /fendou   /struggle
+curse.png           /咒骂   /:-S     /zhm      /curse
+question.png        /疑问   /?       /yiw      /question
+quiet.png           /嘘...  /;x      /xu       /shh
+hypnotized.png      /晕     /;@      /yun      /dizzy
+excruciating.png    /折磨   /:8      /zhem     /excrutiating
+freaked-out.png     /衰     /;!      /shuai    /freaked_out
+skeleton.png        /骷髅   /!!!     /kl       /skeleton
+hammer.png          /敲打   /xx      /qiao     /hammer
+bye.png             /再见   /bye     /zj       /bye
+go-away.png         /闪人   /go      /shan     /go
+tremble.png         /发抖   /shake   /fad      /shake
+in-love.png         /爱情   /love    /aiq      /love
+jump.png            /跳     /jump    /tiao     /jump
+search.png          /找     /find    /zhao     /search
+lashes.png          /美眉   /&       /mm       /beautiful_eyebrows
+pig.png             /猪头   /pig     /zt       /pig
+cat.png             /猫咪   /cat     /mm       /cat
+dog.png             /小狗   /dog     /xg       /dog
+hug-left.png        /拥抱   /hug     /yb       /hug
+coins.png           /钱     /$       /qianc    /money
+lamp.png            /灯泡   /!       /dp       /lightbulb
+bowl.png            /酒杯   /cup     /bei      /cup
+cake.png            /蛋糕   /cake    /dg       /cake
+thunder.png         /闪电   /li      /shd      /lightning
+bomb.png            /炸弹   /bome    /zhd      /bomb
+knife.png           /刀     /kn      /dao      /knife
+soccerball.png      /足球   /footb   /zq       /soccer
+musical-note.png    /音乐   /music   /yy       /music
+poop.png            /便便   /shit    /bb       /shit
+coffee.png          /咖啡   /coffee  /kf       /coffee
+eat.png             /饭     /eat     /fan      /eat
+pill.png            /药丸   /pill    /yw       /pill
+rose.png            /玫瑰   /rose    /mg       /rose
+wilt.png            /凋谢   /fade    /dx       /wilt
+kiss.png            /吻     /kiss    /wen      /kiss
+love.png            /爱心   /heart   /xin      /heart
+love-over.png       /心碎   /break   /xs       /broken_heart
+meeting.png         /会议   /meeting /hy       /meeting
+present.png         /礼物   /gift    /lw       /gift
+phone.png           /电话   /phone   /dh       /phone
+clock.png           /时间   /time    /sj       /time
+mail.png            /邮件   /email   /yj       /email
+tv.png              /电视   /TV      /ds       /TV
+sun.png             /太阳   /sun     /ty       /sun
+moon.png            /月亮   /moon    /yl       /moon
+good.png            /强     /strong  /qiang    /thumbs_up
+bad.png             /弱     /weak    /ruo      /thumbs_down
+handshake.png       /握手   /share   /ws       /handshake
+victory.png         /胜利   /v       /shl      /victory
+beauty.png          /美女   /<J>     /mn       /beauty
+qq.png              /Q仔    /<QQ>    /qz       /qq
+blowkiss.png        /飞吻   /<L>     /fw       /blow_kiss
+angry.png           /怄火   /<O>     /oh       /angry
+liquor.png          /白酒   /<B>     /bj       /baijiu
+can.png             /汽水   /<U>     /qsh      /soda
+watermelon.png      /西瓜   /<W>     /xigua    /watermelon
+rain.png            /下雨   /<!!>    /xy       /rain
+cloudy.png          /多云   /<~>     /duoy     /cloudy
+snowman.png         /雪人   /<Z>     /xr       /snowman
+star.png            /星星   /<*>     /xixing   /star
+girl.png            /女     /<00>    /nv       /woman
+boy.png             /男     /<11>    /nan      /man
+! skywalker.png     C:-)    c:-)    C:)     c:)
+! monkey.png        :-(|)
+
+### Following ICQ 5.1
+[ICQ]
+smile.png           :-)     :)
+sad.png             :-(     :(
+wink.png            ;-)     ;)
+tongue.png          :-P     :P
+laugh.png           *JOKINGLY*
+crying.png          :'(
+#*KISSED*
+kiss.png            :-*
+embarrassed.png     :-[
+angel.png           O:-)
+shut-mouth.png      :-X     :X
+thinking.png        :-\\    :-/
+shout.png           >:o     >:O
+smile-big.png       :-D     :D
+moneymouth.png      :-$
+shock.png           =-O
+glasses-cool.png    8-)
+#[:-}
+sleepy.png          *TIRED*
+sick.png            :-!
+#*STOP*
+#*KISSING* 
+devil.png           ]:->
+rose.png            @}->--
+bomb.png            @=
+good.png            *THUMBS\ UP*
+beer.png            *DRINK*
+in-love.png         *IN\ LOVE*
+! skywalker.png     C:-)    c:-)    C:)     c:)
+! monkey.png        :-(|)
+
+### Following Yahoo! Messenger 8.1
+[Yahoo]
+smile.png           :)      :-)
+question.png        :-/     :-\\
+shock.png           :-O     :O      :-o     :o 
+devil.png           >:)
+angel.png           O:-)    o:-)    0:-)
+sick.png            :-&
+yawn.png            (:|
+hypnotized.png      @-)
+#on_the_phone       :)]     MISSING: "Wait,I'm phoning!" (not phone.png)    => smily showing phone and hand ("stop")
+sad.png             :(      :-(
+in-love.png         :x      :-x     :X      :-X
+angry.png           X-(     x-(     X(      x(
+crying.png          :((
+glasses-nerdy.png   :-B     :-b
+quiet.png           :-$
+drool.png           =P~     =p~
+lying.png           :^O     :^o
+call-me.png         :-c
+wink.png            ;)      ;-)
+embarrassed.png     :">
+mean.png            :->     :>
+laugh.png           :))     :-))
+bye.png             =;
+arrogant.png        [-(
+thinking.png        :-?
+waiting.png         :-w     :-W
+#at_wits_end        ~x(     ~X(     MISSING: "Why.Does.This.Not.Work.AAAAARGH!!"    => angry smily shouting and pulling hair off
+smile-big.png       :D      :-D     :d      :-d
+tongue.png          :-P     :P      :-p     :p
+glasses-cool.png    B-)     b-)
+neutral.png         :|      :-|
+sleepy.png          I-)     i-)     |-)
+clown.png           :o)     :O)
+doh.png             #-o     #-O
+weep.png            :-<
+go-away.png         :-h
+lashes.png          ;;)
+kiss.png            :-*     :*
+confused.png        :-S     :-s
+sarcastic.png       /:)
+eyeroll.png         8-|
+silly.png           8-}
+clap.png            =D>     =d>
+mad-tongue.png      >:P     >:p
+#timeout            :-t     :-T     MISSING: "Let's have a break."
+hug-left.png        >:D<    >:d<
+love-over.png       =((
+sweat.png           #:-S    #:-s
+rotfl.png           =))    
+#loser              L-)     l-)     MISSING/YAHOO 6: "Loser!"
+party.png           <:-P    <:-p
+nailbiting.png      :-SS	:-Ss	:-sS	:-ss
+cowboy.png          <):)
+desire.png          8->
+! skywalker.png     C:-)    c:-)    C:)     c:)
+! monkey.png        :-(|)
+
+### Hidden Yahoo emotes
+alien.png           =:)     >-)
+beat-up.png         b-(     B-(
+chicken.png         ~:>
+coffee.png          ~o)     ~O)
+cow.png             3:-O    3:-o
+dance.png           \\:D/   \\:d/
+rose.png            @};-
+dont-know.png       :-L     :-l
+skeleton.png        8-X     8-x
+lamp.png            *-:)
+monkey.png          :(|)
+coins.png           $-)
+peace.png           :)>-
+pig.png             :@)
+pray.png            [-o<    [-O<
+pumpkin.png         (~~)
+shame.png           [-X     [-x
+flag.png            **==
+clover.png          %%-
+musical-note.png    :-"
+giggle.png          ;))
+worship.png         ^:)^
+star.png            (*)
+#waving.png         >:/
+#talktohand.png     :-@
+#youkiddingme.png   :-j :-J
+
+### These only work in a certain IMvironment
+#malefighter1.png   o->     O->
+#malefighter2.png   o=>     O=>
+#femalefighter.png  o-+     O-+
+yin-yang.png        (%)
+
--- a/pidgin/pixmaps/emotes/default/22/theme	Thu Jun 14 19:48:48 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,358 +0,0 @@
-Name=Default
-Description=Pidgin smileys
-Icon=smile.png
-Author=Hylke Bons
-
-# default smileys
-[default]
-smile.png           :)      :-)
-smile-big.png       :-D     :-d     :D      :d
-sad.png             :-(     :(
-wink.png            ;-)     ;)
-tongue.png          :P      :-P     :-p     :p
-shock.png           =-O     =-o
-kiss.png            :-*
-glasses-cool.png    8-)
-embarrassed.png     :-[
-crying.png          :'(
-thinking.png        :-/     :-\\
-angel.png           O:-)    o:-)
-shut-mouth.png      :-X
-moneymouth.png      :-$
-foot-in-mouth.png   :-!
-shout.png           >:o     >:O
-! skywalker.png     C:-)    c:-)    C:)     c:)
-! monkey.png        :-(|)
-
-### Following AIM 6.1
-[AIM]
-smile.png           :-)     :)
-wink.png            ;-)     ;)
-sad.png             :-(     :(
-tongue.png          :-P     :P
-shock.png           =-O
-kiss.png            :-*
-shout.png           >:o
-smile-big.png       :-D     :D
-moneymouth.png      :-$
-foot-in-mouth.png   :-!
-embarrassed.png     :-[
-angel.png           O:-)
-thinking.png        :-\\    :-/
-crying.png          :'(
-shut-mouth.png      :-X
-glasses-cool.png    8-)
-! skywalker.png     C:-)    c:-)    C:)     c:)
-! monkey.png        :-(|)
-
-### Following Windows Live Messenger 8.1
-[MSN]
-smile.png           :)      :-)
-smile-big.png       :D      :d :-D :-d
-wink.png            ;)      ;-)
-shock.png           :-O     :-o :O :o
-tongue.png          :P      :p :-P :-p
-glasses-cool.png    (H)     (h)
-angry.png           :@      :-@
-embarrassed.png     :$      :-$
-confused.png        :S      :s :-S :-s
-sad.png             :(      :-(
-crying.png          :'(
-neutral.png         :|      :-|
-devil.png           (6)
-angel.png           (A)     (a)
-love.png            (L)     (l)
-love-over.png       (U)     (u)
-msn.png             (M)     (m)
-cat.png             (@)
-dog.png             (&)
-moon.png            (S)
-star.png            (*)
-film.png            (~)
-musical-note.png    (8)
-mail.png            (E)     (e)
-rose.png            (F)     (f)
-rose-dead.png       (W)     (w)
-clock.png           (O)     (o)
-kiss.png            (K)     (k)
-present.png         (G)     (g)
-cake.png            (^)
-camera.png          (P)     (p)
-lamp.png            (I)     (i)
-coffee.png          (C)     (c)
-phone.png           (T)     (t)
-hug-left.png        ({)
-hug-right.png       (})
-beer.png            (B)     (b)
-drink.png           (D)     (d)
-boy.png             (Z)     (z)
-girl.png            (X)     (x)
-good.png            (Y)     (y)
-bad.png             (N)     (n)
-vampire.png         :[      :-[
-#goat.png           (nah)
-sun.png             (#)
-rainbow.png         (R)     (r)
-quiet.png           :-#
-teeth.png           8o|
-glasses-nerdy.png   8-|
-sarcastic.png       ^o)
-secret.png          :-*
-sick.png            +o(
-snail.png           (sn)
-turtle.png          (tu)
-plate.png           (pl)
-bowl.png            (||)
-pizza.png           (pi)
-soccerball.png      (so)
-car.png             (au)
-airplane.png        (ap)
-umbrella.png        (um)
-island.png          (ip)
-computer.png        (co)
-mobile.png          (mp)
-brb.png             (brb)
-rain.png            (st)
-highfive.png        (h5)
-coins.png           (mo)
-sheep.png           (bah)
-dont-know.png       :^)
-thinking.png        *-)
-thunder.png         (li)
-party.png           <:o)
-eyeroll.png         8-)
-yawn.png            |-) 
-goat.png            (nah)
-! skywalker.png     C:-)    c:-)    C:)     c:)
-! monkey.png        :-(|)
-
-### Hidden MSN emotes
-sigarette.png      	(ci)    (CI)
-handcuffs.png       (%)
-console.png			(xx)    (XX)
-fingers-crossed.png	(yn)    (YN)
-
-### Following QQ 2006
-[QQ]
-shock.png           /惊讶   /:O      /jy       /surprised
-curl-lip.png        /撇嘴   /:~      /pz       /curl_lip
-desire.png          /色     /:*      /se       /desire
-dazed.png           /发呆   /:|      /dazed
-party.png           /得意   /8-)     /dy       /revel
-crying.png          /流泪   /:<      /ll       /cry
-bashful.png         /害羞   /:$      /hx       /bashful
-shut-mouth.png      /闭嘴   /:X      /bz       /shut_mouth
-sleepy.png          /睡     /:Z      /shui     /sleep
-weep.png            /大哭   /:'(     /dk       /weep
-embarrassed.png     /尴尬   /:-|     /gg       /embarassed
-pissed-off.png      /发怒   /:@      /fn       /pissed_off
-act-up.png          /调皮   /:P      /tp       /act_up
-smile-big.png       /呲牙   /:D      /cy       /toothy_smile
-smile.png           /微笑   /:)      /wx       /small_smile
-sad.png             /难过   /:(      /ng       /sad
-glasses-cool.png    /酷     /:+      /kuk      /cool
-doctor.png          /非典   /:#      /feid     /SARS
-silly.png           /抓狂   /:Q      /zk       /crazy
-sick.png            /吐     /:T      /tu       /vomit
-snicker.png         /偷笑   /;p      /tx       /titter
-cute.png            /可爱   /;-D     /ka       /cute
-disdain.png         /白眼   /;d      /by       /disdain
-arrogant.png        /傲慢   /;o      /am       /arrogant
-starving.png        /饥饿   /:g      /jie      /starving
-yawn.png            /困     /|-)     /kun      /sleepy
-terror.png          /惊恐   /:!      /jk       /terror
-sweat.png           /流汗   /:L      /sweat
-smirk.png           /憨笑   /:>      /hanx     /smirk
-soldier.png         /大兵   /:;      /db       /soldier
-struggle.png        /奋斗   /;f      /fendou   /struggle
-curse.png           /咒骂   /:-S     /zhm      /curse
-question.png        /疑问   /?       /yiw      /question
-quiet.png           /嘘...  /;x      /xu       /shh
-hypnotized.png      /晕     /;@      /yun      /dizzy
-excruciating.png    /折磨   /:8      /zhem     /excrutiating
-freaked-out.png     /衰     /;!      /shuai    /freaked_out
-skeleton.png        /骷髅   /!!!     /kl       /skeleton
-hammer.png          /敲打   /xx      /qiao     /hammer
-bye.png             /再见   /bye     /zj       /bye
-go-away.png         /闪人   /go      /shan     /go
-tremble.png         /发抖   /shake   /fad      /shake
-in-love.png         /爱情   /love    /aiq      /love
-jump.png            /跳     /jump    /tiao     /jump
-search.png          /找     /find    /zhao     /search
-lashes.png          /美眉   /&       /mm       /beautiful_eyebrows
-pig.png             /猪头   /pig     /zt       /pig
-cat.png             /猫咪   /cat     /mm       /cat
-dog.png             /小狗   /dog     /xg       /dog
-hug-left.png        /拥抱   /hug     /yb       /hug
-coins.png           /钱     /$       /qianc    /money
-lamp.png            /灯泡   /!       /dp       /lightbulb
-bowl.png            /酒杯   /cup     /bei      /cup
-cake.png            /蛋糕   /cake    /dg       /cake
-thunder.png         /闪电   /li      /shd      /lightning
-bomb.png            /炸弹   /bome    /zhd      /bomb
-knife.png           /刀     /kn      /dao      /knife
-soccerball.png      /足球   /footb   /zq       /soccer
-musical-note.png    /音乐   /music   /yy       /music
-poop.png            /便便   /shit    /bb       /shit
-coffee.png          /咖啡   /coffee  /kf       /coffee
-eat.png             /饭     /eat     /fan      /eat
-pill.png            /药丸   /pill    /yw       /pill
-rose.png            /玫瑰   /rose    /mg       /rose
-wilt.png            /凋谢   /fade    /dx       /wilt
-kiss.png            /吻     /kiss    /wen      /kiss
-love.png            /爱心   /heart   /xin      /heart
-love-over.png       /心碎   /break   /xs       /broken_heart
-meeting.png         /会议   /meeting /hy       /meeting
-present.png         /礼物   /gift    /lw       /gift
-phone.png           /电话   /phone   /dh       /phone
-clock.png           /时间   /time    /sj       /time
-mail.png            /邮件   /email   /yj       /email
-tv.png              /电视   /TV      /ds       /TV
-sun.png             /太阳   /sun     /ty       /sun
-moon.png            /月亮   /moon    /yl       /moon
-good.png            /强     /strong  /qiang    /thumbs_up
-bad.png             /弱     /weak    /ruo      /thumbs_down
-handshake.png       /握手   /share   /ws       /handshake
-victory.png         /胜利   /v       /shl      /victory
-beauty.png          /美女   /<J>     /mn       /beauty
-qq.png              /Q仔    /<QQ>    /qz       /qq
-blowkiss.png        /飞吻   /<L>     /fw       /blow_kiss
-angry.png           /怄火   /<O>     /oh       /angry
-liquor.png          /白酒   /<B>     /bj       /baijiu
-can.png             /汽水   /<U>     /qsh      /soda
-watermelon.png      /西瓜   /<W>     /xigua    /watermelon
-rain.png            /下雨   /<!!>    /xy       /rain
-cloudy.png          /多云   /<~>     /duoy     /cloudy
-snowman.png         /雪人   /<Z>     /xr       /snowman
-star.png            /星星   /<*>     /xixing   /star
-girl.png            /女     /<00>    /nv       /woman
-boy.png             /男     /<11>    /nan      /man
-! skywalker.png     C:-)    c:-)    C:)     c:)
-! monkey.png        :-(|)
-
-### Following ICQ 5.1
-[ICQ]
-smile.png           :-)     :)
-sad.png             :-(     :(
-wink.png            ;-)     ;)
-tongue.png          :-P     :P
-laugh.png           *JOKINGLY*
-crying.png          :'(
-#*KISSED*
-kiss.png            :-*
-embarrassed.png     :-[
-angel.png           O:-)
-shut-mouth.png      :-X     :X
-thinking.png        :-\\    :-/
-shout.png           >:o     >:O
-smile-big.png       :-D     :D
-moneymouth.png      :-$
-shock.png           =-O
-glasses-cool.png    8-)
-#[:-}
-sleepy.png          *TIRED*
-sick.png            :-!
-#*STOP*
-#*KISSING* 
-devil.png           ]:->
-rose.png            @}->--
-bomb.png            @=
-good.png            *THUMBS\ UP*
-beer.png            *DRINK*
-in-love.png         *IN\ LOVE*
-! skywalker.png     C:-)    c:-)    C:)     c:)
-! monkey.png        :-(|)
-
-### Following Yahoo! Messenger 8.1
-[Yahoo]
-smile.png           :)      :-)
-question.png        :-/     :-\\
-shock.png           :-O     :O      :-o     :o 
-devil.png           >:)
-angel.png           O:-)    o:-)    0:-)
-sick.png            :-&
-yawn.png            (:|
-hypnotized.png      @-)
-#on_the_phone       :)]     MISSING: "Wait,I'm phoning!" (not phone.png)    => smily showing phone and hand ("stop")
-sad.png             :(      :-(
-in-love.png         :x      :-x     :X      :-X
-angry.png           X-(     x-(     X(      x(
-crying.png          :((
-glasses-nerdy.png   :-B     :-b
-quiet.png           :-$
-drool.png           =P~     =p~
-lying.png           :^O     :^o
-call-me.png         :-c
-wink.png            ;)      ;-)
-embarrassed.png     :">
-mean.png            :->     :>
-laugh.png           :))     :-))
-bye.png             =;
-arrogant.png        [-(
-thinking.png        :-?
-waiting.png         :-w     :-W
-#at_wits_end        ~x(     ~X(     MISSING: "Why.Does.This.Not.Work.AAAAARGH!!"    => angry smily shouting and pulling hair off
-smile-big.png       :D      :-D     :d      :-d
-tongue.png          :-P     :P      :-p     :p
-glasses-cool.png    B-)     b-)
-neutral.png         :|      :-|
-sleepy.png          I-)     i-)     |-)
-clown.png           :o)     :O)
-doh.png             #-o     #-O
-weep.png            :-<
-go-away.png         :-h
-lashes.png          ;;)
-kiss.png            :-*     :*
-confused.png        :-S     :-s
-sarcastic.png       /:)
-eyeroll.png         8-|
-silly.png           8-}
-clap.png            =D>     =d>
-mad-tongue.png      >:P     >:p
-#timeout            :-t     :-T     MISSING: "Let's have a break."
-hug-left.png        >:D<    >:d<
-love-over.png       =((
-sweat.png           #:-S    #:-s
-rotfl.png           =))    
-#loser              L-)     l-)     MISSING/YAHOO 6: "Loser!"
-party.png           <:-P    <:-p
-nailbiting.png      :-SS	:-Ss	:-sS	:-ss
-cowboy.png          <):)
-desire.png          8->
-! skywalker.png     C:-)    c:-)    C:)     c:)
-! monkey.png        :-(|)
-
-### Hidden Yahoo emotes
-alien.png           =:)     >-)
-beat-up.png         b-(     B-(
-chicken.png         ~:>
-coffee.png          ~o)     ~O)
-cow.png             3:-O    3:-o
-dance.png           \\:D/   \\:d/
-rose.png            @};-
-dont-know.png       :-L     :-l
-skeleton.png        8-X     8-x
-lamp.png            *-:)
-monkey.png          :(|)
-coins.png           $-)
-peace.png           :)>-
-pig.png             :@)
-pray.png            [-o<    [-O<
-pumpkin.png         (~~)
-shame.png           [-X     [-x
-flag.png            **==
-clover.png          %%-
-musical-note.png    :-"
-giggle.png          ;))
-worship.png         ^:)^
-star.png            (*)
-#waving.png         >:/
-#talktohand.png     :-@
-#youkiddingme.png   :-j :-J
-
-### These only work in a certain IMvironment
-#malefighter1.png   o->     O->
-#malefighter2.png   o=>     O=>
-#femalefighter.png  o-+     O-+
-yin-yang.png        (%)
-
--- a/pidgin/pixmaps/emotes/none/Makefile.am	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/emotes/none/Makefile.am	Mon Jun 18 01:48:35 2007 +0000
@@ -1,5 +1,13 @@
 pidginsmileypixdir = $(datadir)/pixmaps/pidgin/emotes/none
+pidginsmileypix_in_files = none.theme.in
 pidginsmileypix_DATA = theme
 
+theme: none.theme.in
+	sed -e 's/^_Name=/Name=/' \
+	    -e 's/^_Description=/Description=/' \
+	    -e 's/^_Author=/Author=/' \
+	$< > $@
+
 EXTRA_DIST = $(pidginsmileypix_DATA) \
+	$(pidginsmileypix_in_files) \
 	Makefile.mingw
--- a/pidgin/pixmaps/emotes/none/Makefile.mingw	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/emotes/none/Makefile.mingw	Mon Jun 18 01:48:35 2007 +0000
@@ -10,11 +10,14 @@
 datadir = $(PIDGIN_INSTALL_DIR)
 include ./Makefile.am
 
-.PHONY: install
+.PHONY: install clean
 
-install:
+install: theme
 	if test '$(pidginsmileypix_DATA)'; then \
 	  mkdir -p $(pidginsmileypixdir); \
 	  cp $(pidginsmileypix_DATA) $(pidginsmileypixdir); \
 	fi;
 
+clean:
+	rm -f theme
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pixmaps/emotes/none/none.theme.in	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,3 @@
+_Name=none
+_Description=Selecting this disables graphical emoticons.
+_Author=Penguin Pimps
--- a/pidgin/pixmaps/emotes/none/theme	Thu Jun 14 19:48:48 2007 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-Name=none
-Description=Selecting this disables graphical emoticons.
-Author=Penguin Pimps
Binary file pidgin/pixmaps/icons/16/pidgin.png has changed
--- a/pidgin/pixmaps/icons/16/scalable/pidgin.svg	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/icons/16/scalable/pidgin.svg	Mon Jun 18 01:48:35 2007 +0000
@@ -14,7 +14,7 @@
    id="svg4345"
    sodipodi:version="0.32"
    inkscape:version="0.44.1"
-   sodipodi:docbase="/home/hbons/Desktop/icons/16/scalable"
+   sodipodi:docbase="/home/hbons/Desktop/2.0.2/pidgin/pixmaps/icons/16/scalable"
    sodipodi:docname="pidgin.svg"
    inkscape:export-filename="/home/hbons/Desktop/pidgin16.png"
    inkscape:export-xdpi="90"
@@ -24,6 +24,54 @@
      id="defs4347">
     <linearGradient
        inkscape:collect="always"
+       id="linearGradient3157">
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:1;"
+         offset="0"
+         id="stop3159" />
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:0;"
+         offset="1"
+         id="stop3161" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3149">
+      <stop
+         style="stop-color:#3b1941;stop-opacity:1;"
+         offset="0"
+         id="stop3151" />
+      <stop
+         style="stop-color:#3b1941;stop-opacity:0;"
+         offset="1"
+         id="stop3153" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3141">
+      <stop
+         style="stop-color:#82508e;stop-opacity:1;"
+         offset="0"
+         id="stop3143" />
+      <stop
+         style="stop-color:#82508e;stop-opacity:0;"
+         offset="1"
+         id="stop3145" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3128">
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:1;"
+         offset="0"
+         id="stop3130" />
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:0;"
+         offset="1"
+         id="stop3132" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
        id="linearGradient5438">
       <stop
          style="stop-color:white;stop-opacity:1;"
@@ -72,18 +120,6 @@
     </linearGradient>
     <linearGradient
        inkscape:collect="always"
-       id="linearGradient5304">
-      <stop
-         style="stop-color:#2e3436;stop-opacity:1;"
-         offset="0"
-         id="stop5306" />
-      <stop
-         style="stop-color:#2e3436;stop-opacity:0;"
-         offset="1"
-         id="stop5308" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
        id="linearGradient5280">
       <stop
          style="stop-color:#82508e;stop-opacity:1;"
@@ -178,24 +214,6 @@
        gradientUnits="userSpaceOnUse" />
     <linearGradient
        inkscape:collect="always"
-       xlink:href="#linearGradient5304"
-       id="linearGradient5310"
-       x1="12.606371"
-       y1="15.069461"
-       x2="12.606371"
-       y2="21.152372"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6506"
-       id="linearGradient6512"
-       x1="15.645709"
-       y1="39.743458"
-       x2="15.645709"
-       y2="53.502155"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
        xlink:href="#linearGradient6537"
        id="linearGradient6543"
        x1="30.5"
@@ -211,7 +229,8 @@
        y1="38.950283"
        x2="5.7089725"
        y2="42.982571"
-       gradientUnits="userSpaceOnUse" />
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.63556,0,0,0.371995,11.16667,-5.489292)" />
     <linearGradient
        inkscape:collect="always"
        xlink:href="#linearGradient5438"
@@ -221,6 +240,421 @@
        x2="30.152058"
        y2="23.011967"
        gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3976">
+      <stop
+         style="stop-color:#3b1941;stop-opacity:1;"
+         offset="0"
+         id="stop3978" />
+      <stop
+         style="stop-color:#3b1941;stop-opacity:0;"
+         offset="1"
+         id="stop3980" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3968">
+      <stop
+         style="stop-color:#82508e;stop-opacity:1;"
+         offset="0"
+         id="stop3970" />
+      <stop
+         style="stop-color:#82508e;stop-opacity:0;"
+         offset="1"
+         id="stop3972" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3958">
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:1;"
+         offset="0"
+         id="stop3960" />
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:0;"
+         offset="1"
+         id="stop3962" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2850">
+      <stop
+         style="stop-color:#ce5c00;stop-opacity:1;"
+         offset="0"
+         id="stop2852" />
+      <stop
+         style="stop-color:#ce5c00;stop-opacity:0;"
+         offset="1"
+         id="stop2854" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient6563">
+      <stop
+         style="stop-color:white;stop-opacity:1;"
+         offset="0"
+         id="stop6565" />
+      <stop
+         style="stop-color:white;stop-opacity:0;"
+         offset="1"
+         id="stop6567" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2110">
+      <stop
+         style="stop-color:black;stop-opacity:0;"
+         offset="0"
+         id="stop2112" />
+      <stop
+         id="stop2114"
+         offset="0.5"
+         style="stop-color:black;stop-opacity:1;" />
+      <stop
+         style="stop-color:black;stop-opacity:0;"
+         offset="1"
+         id="stop2067" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient25546"
+       id="radialGradient2069"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.994693,0,4.16407e-2)"
+       cx="7.8836637"
+       cy="1.5104795"
+       fx="7.8836637"
+       fy="1.5104795"
+       r="8.4883642" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient25546"
+       id="radialGradient2071"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.994693,0,4.16407e-2)"
+       cx="7.8836741"
+       cy="0.14505707"
+       fx="7.8836741"
+       fy="0.14505707"
+       r="8.4883642" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient25546"
+       id="radialGradient2079"
+       cx="7.8836637"
+       cy="2.6242435"
+       fx="7.8836637"
+       fy="2.6242435"
+       r="8.4883642"
+       gradientTransform="matrix(1.131317,0,0,1.125313,-1.035262,-0.301139)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient2081">
+      <stop
+         style="stop-color:#f4d9b1;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop2104" />
+      <stop
+         style="stop-color:#df9725;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop2085" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6506"
+       id="linearGradient2101"
+       x1="15.645709"
+       y1="39.743458"
+       x2="14.943421"
+       y2="50.079575"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6537"
+       id="linearGradient2089"
+       x1="30.5"
+       y1="0.033532728"
+       x2="30.5"
+       y2="23.559282"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6563"
+       id="linearGradient6569"
+       x1="-1.6841649"
+       y1="39.902092"
+       x2="5.5366187"
+       y2="44.272076"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="23.011967"
+       x2="30.152058"
+       y1="-0.86487341"
+       x1="30.152058"
+       id="linearGradient2097"
+       xlink:href="#linearGradient5438"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="42.982571"
+       x2="5.7089725"
+       y1="38.950283"
+       x1="0.23931108"
+       id="linearGradient2095"
+       xlink:href="#linearGradient6817"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="50.726673"
+       x2="15.645709"
+       y1="40.434063"
+       x1="15.645709"
+       id="linearGradient2093"
+       xlink:href="#linearGradient6506"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2087">
+      <stop
+         id="stop2089"
+         offset="0.0000000"
+         style="stop-color:#f4d9b1;stop-opacity:1.0000000;" />
+      <stop
+         id="stop2091"
+         offset="1.0000000"
+         style="stop-color:#df9725;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.131317,0,0,1.125313,-1.035262,-0.301139)"
+       r="8.4883642"
+       fy="2.6242435"
+       fx="7.8836637"
+       cy="2.6242435"
+       cx="7.8836637"
+       id="radialGradient2085"
+       xlink:href="#linearGradient25546"
+       inkscape:collect="always" />
+    <radialGradient
+       r="8.4883642"
+       fy="0.14505707"
+       fx="7.8836741"
+       cy="0.14505707"
+       cx="7.8836741"
+       gradientTransform="matrix(1,0,0,0.994693,0,4.16407e-2)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2077"
+       xlink:href="#linearGradient25546"
+       inkscape:collect="always" />
+    <radialGradient
+       r="8.4883642"
+       fy="1.5104795"
+       fx="7.8836637"
+       cy="1.5104795"
+       cx="7.8836637"
+       gradientTransform="matrix(1,0,0,0.994693,0,4.16407e-2)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2075"
+       xlink:href="#linearGradient25546"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2067">
+      <stop
+         id="stop2069"
+         offset="0"
+         style="stop-color:black;stop-opacity:0;" />
+      <stop
+         style="stop-color:black;stop-opacity:1;"
+         offset="0.5"
+         id="stop2071" />
+      <stop
+         id="stop2073"
+         offset="1"
+         style="stop-color:black;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3108"
+       inkscape:collect="always">
+      <stop
+         id="stop3110"
+         offset="0"
+         style="stop-color:#eeeeec;stop-opacity:1;" />
+      <stop
+         id="stop3112"
+         offset="1"
+         style="stop-color:#eeeeec;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3116"
+       inkscape:collect="always">
+      <stop
+         id="stop3118"
+         offset="0"
+         style="stop-color:#82508e;stop-opacity:1;" />
+      <stop
+         id="stop3120"
+         offset="1"
+         style="stop-color:#82508e;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3124"
+       inkscape:collect="always">
+      <stop
+         id="stop3126"
+         offset="0"
+         style="stop-color:#3b1941;stop-opacity:1;" />
+      <stop
+         id="stop3128"
+         offset="1"
+         style="stop-color:#3b1941;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2850"
+       id="linearGradient2187"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.769231,0,0,0.714287,47.76924,-9.285729)"
+       x1="21.785719"
+       y1="28.142857"
+       x2="17.785713"
+       y2="30.07143" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2850"
+       id="linearGradient2195"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.769231,0,0,0.714287,13.76923,-8.28573)"
+       x1="21.785719"
+       y1="28.142857"
+       x2="17.785713"
+       y2="30.07143" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3958"
+       id="radialGradient2209"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.116159,0,0,1.076653,14.60502,-22.28695)"
+       cx="9.0640488"
+       cy="21.511742"
+       fx="9.0640488"
+       fy="21.511742"
+       r="16.663956" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6506"
+       id="linearGradient2211"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.660903,0,0,0.627207,18.73149,-12.3201)"
+       x1="15.645709"
+       y1="39.743458"
+       x2="15.645709"
+       y2="53.502155" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3968"
+       id="linearGradient2214"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.67692,0,0,0.646801,18.46433,-12.90841)"
+       x1="16.13257"
+       y1="40.781811"
+       x2="16.13257"
+       y2="48.068741" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3976"
+       id="linearGradient2216"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.67692,0,0,0.646801,18.46433,-12.90841)"
+       x1="12.095973"
+       y1="40.907658"
+       x2="12.095973"
+       y2="46.463146" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6537"
+       id="linearGradient2219"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.668893,0,0,0.668627,18.08624,-12.19246)"
+       x1="30.5"
+       y1="0.033532728"
+       x2="30.5"
+       y2="23.559282" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3108"
+       id="linearGradient2229"
+       gradientUnits="userSpaceOnUse"
+       x1="10.18327"
+       y1="16.618088"
+       x2="27.598003"
+       y2="36.64465"
+       gradientTransform="matrix(0.660903,0,0,0.627207,49.74106,-7.361383)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6506"
+       id="linearGradient2231"
+       gradientUnits="userSpaceOnUse"
+       x1="15.645709"
+       y1="39.743458"
+       x2="15.645709"
+       y2="53.502155"
+       gradientTransform="matrix(0.660903,0,0,0.627207,49.74106,-7.361383)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3116"
+       id="linearGradient2234"
+       gradientUnits="userSpaceOnUse"
+       x1="15.722902"
+       y1="39.585075"
+       x2="15.722902"
+       y2="45.76453"
+       gradientTransform="matrix(0.67692,0,0,0.646801,49.4739,-7.949693)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3124"
+       id="linearGradient2236"
+       gradientUnits="userSpaceOnUse"
+       x1="13.150809"
+       y1="39.39394"
+       x2="13.150809"
+       y2="45.551888"
+       gradientTransform="matrix(0.67692,0,0,0.646801,49.4739,-7.949693)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3128"
+       id="linearGradient3134"
+       x1="8.0725698"
+       y1="17.765934"
+       x2="24.284664"
+       y2="37.578945"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3141"
+       id="linearGradient3147"
+       x1="12.353984"
+       y1="38.611191"
+       x2="12.353984"
+       y2="45.595356"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient3155"
+       x1="10.166225"
+       y1="38.766953"
+       x2="10.166225"
+       y2="45.595673"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3157"
+       id="linearGradient3163"
+       x1="11.982447"
+       y1="39.088425"
+       x2="11.982447"
+       y2="45.778931"
+       gradientUnits="userSpaceOnUse" />
   </defs>
   <sodipodi:namedview
      id="base"
@@ -229,17 +663,17 @@
      borderopacity="1.0"
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
-     inkscape:zoom="42.440064"
-     inkscape:cx="13.087113"
-     inkscape:cy="8.5298663"
+     inkscape:zoom="30.009658"
+     inkscape:cx="12.410351"
+     inkscape:cy="9.6914614"
      inkscape:current-layer="layer1"
      showgrid="true"
      inkscape:grid-bbox="true"
      inkscape:document-units="px"
-     inkscape:window-width="1274"
-     inkscape:window-height="966"
-     inkscape:window-x="3"
-     inkscape:window-y="25"
+     inkscape:window-width="1434"
+     inkscape:window-height="840"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
      showguides="true"
      inkscape:guide-bbox="true"
      inkscape:grid-points="false"
@@ -268,7 +702,7 @@
        transform="matrix(1.148904,0,0,0.920169,-34.28919,-3.241212)"
        sodipodi:nodetypes="csccccc" />
     <path
-       style="opacity:1;fill:#82508e;fill-opacity:1;stroke:#3b1941;stroke-width:2.30209565;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       style="opacity:1;fill:url(#linearGradient3147);fill-opacity:1.0;stroke:url(#linearGradient3155);stroke-width:2.30209565;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
        d="M 15,13 C 8.3759979,13 3,18.600001 3,25.5 C 3,31.153143 2.9750563,38.402618 2.9750563,45.572826 C 4.1625449,45.572826 27.946366,45.600605 30.637365,45.600605 C 32.751492,45.600605 32.586331,43.541005 32.586331,43.541005 C 32.586331,40.875594 27.597902,38.639057 25.813453,36.682531 C 23.985035,34.68151 26,30.884078 26,30.884078 C 26.641306,29.354278 28.01889,26.891006 28.01889,25.115922 C 28.01889,18.215923 21.624002,13 15,13 z "
        id="path5176"
        sodipodi:nodetypes="ccccszcsc"
@@ -284,34 +718,17 @@
        ry="0.32910046"
        transform="matrix(1.147027,0,0,0.866113,-0.324314,2.386999)" />
     <path
-       sodipodi:type="arc"
-       style="opacity:1;fill:url(#radialGradient5286);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path5273"
-       sodipodi:cx="15.004828"
-       sodipodi:cy="39.80859"
-       sodipodi:rx="9.7225161"
-       sodipodi:ry="7.119638"
-       d="M 24.727345 39.80859 A 9.7225161 7.119638 0 1 1  5.2823124,39.80859 A 9.7225161 7.119638 0 1 1  24.727345 39.80859 z"
-       transform="matrix(0.434788,0,0,0.500648,-1.130366,-6.547801)" />
-    <path
-       style="opacity:0.5152838;fill:#5c3466;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M -42.833794,49.038847 C -42.833794,49.038847 -42.815855,44.709724 -42.815855,37.951005 C -42.815855,37.951005 -39.03087,40.509965 -38.631892,41.678764 C -39.153711,41.596001 -40.372039,41.685633 -40.372039,41.685633 C -40.038351,42.463101 -38.163796,45.952105 -36.121045,48.058218 C -37.780497,47.329365 -39.471111,47.196178 -39.471111,47.196178 C -39.009636,48.111847 -37.250115,48.69173 -36.943887,49.110993 C -36.943887,49.110993 -41.348464,49.038847 -42.833794,49.038847 z "
-       id="rect5312"
-       sodipodi:nodetypes="cccccccc"
-       transform="matrix(0.446908,0,0,0.358425,20.14277,-2.602607)" />
-    <path
-       style="opacity:0.5152838;fill:#5c3466;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M -49.441852,47.4154 C -47.112614,42.001764 -42.19329,43.469796 -40.961409,37.951005 C -40.961409,37.951005 -39.025024,40.280009 -38.974466,41.581367 C -39.496285,41.498604 -39.881988,41.516405 -39.881988,41.516405 C -39.5483,42.293873 -38.196948,45.748112 -36.154197,47.854225 C -37.813649,47.125372 -38.925816,46.898039 -38.925816,46.898039 C -38.847603,47.794771 -38.376224,47.369394 -38.122982,48.215235 C -42.942294,48.046898 -46.252916,49.195571 -49.441852,47.4154 z "
-       id="path5317"
-       sodipodi:nodetypes="cccccccc"
-       transform="matrix(-0.376289,0,0,0.381853,-5.604413,-3.491724)" />
-    <path
        transform="matrix(0.399589,0,0,0.393554,-5.973603e-2,-3.038964)"
-       style="opacity:0.31004363;fill:url(#linearGradient5310);fill-opacity:1;stroke:url(#linearGradient6512);stroke-width:2.5216887;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       style="opacity:0.5;fill:url(#linearGradient3134);fill-opacity:1.0;stroke:url(#linearGradient3163);stroke-width:2.5216887;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
        d="M 15,14.0625 C 8.9877035,14.0625 4.0789961,19.13808 4.0625,25.46875 C 4.0624722,25.479427 4.0617033,25.489349 4.0625,25.5 C 4.0625,32.787473 3.9033639,38.26012 3.9033639,44.499878 C 5.8399452,44.499878 24.86993,44.470084 30.695903,44.470084 C 29.746978,42.549359 26.273076,40.711023 23.972608,38.78763 C 23.362603,37.973536 23.023697,35.459892 22.969233,34.418473 C 23.611113,31.359155 25.129532,28.401757 26.527172,25.440129 C 26.527172,19.094533 21.022436,14.0625 15,14.0625 z "
        id="path5241"
        sodipodi:nodetypes="csccccccc" />
     <path
+       style="opacity:1;fill:#a46bb0;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 6,7.2175674 C 6,8.8735678 4.5070272,10 3.4999996,10 C 2.1199999,10 1,8.6559998 1,6.9999995 C 1,5.5609093 1.7677476,4 3.1477475,4 C 4.5277481,4 6,5.9092686 6,7.2175674 z "
+       id="path3137"
+       sodipodi:nodetypes="csssc" />
+    <path
        transform="matrix(0.626764,0,0,0.689441,-3.309086,-9.833164)"
        style="opacity:1;fill:white;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
        d="M 13.257119,24.626053 C 13.257119,26.227351 11.8279,27.316574 10.863875,27.316574 C 9.5428049,27.316574 8.4706318,26.01697 8.4706318,24.415672 C 8.4706318,23.024119 9.2055946,21.514771 10.526665,21.514771 C 11.847736,21.514771 13.257119,23.360971 13.257119,24.626053 z "
@@ -326,7 +743,12 @@
        sodipodi:rx="1.2410715"
        sodipodi:ry="1.2946428"
        d="M 11.410714 24.3125 A 1.2410715 1.2946428 0 1 1  8.928571,24.3125 A 1.2410715 1.2946428 0 1 1  11.410714 24.3125 z"
-       transform="matrix(0.805756,0,0,0.772414,-5.19425,-11.77932)" />
+       transform="matrix(1.208634,0,0,1.158623,-8.791372,-20.66902)" />
+    <path
+       style="opacity:1;fill:#a46bb0;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 11.387086,4.6790601 C 10.509745,3.6558267 9.0824486,3.9284339 8.5222543,4.5817815 C 7.7545814,5.4771092 7.8435868,7.0342022 8.7209273,8.0574357 C 9.4833498,8.9466415 10.737398,9.413013 11.505071,8.5176851 C 12.272744,7.6223568 12.080215,5.4874505 11.387086,4.6790601 z "
+       id="path3139"
+       sodipodi:nodetypes="csssc" />
     <path
        transform="matrix(0.29055,-0.412361,-0.273947,-0.388798,13.58792,20.45445)"
        style="opacity:1;fill:white;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
@@ -342,30 +764,21 @@
        sodipodi:rx="1.2410715"
        sodipodi:ry="1.2946428"
        d="M 11.410714 24.3125 A 1.2410715 1.2946428 0 1 1  8.928571,24.3125 A 1.2410715 1.2946428 0 1 1  11.410714 24.3125 z"
-       transform="matrix(0.805755,0,0,0.772417,0.805755,-11.77938)" />
+       transform="matrix(1.208633,0,0,1.158626,-2.791363,-20.66909)" />
     <path
-       transform="matrix(0.63556,0,0,0.371992,4.635114,-6.489142)"
-       style="fill:#f9751a;fill-opacity:1;stroke:none;stroke-width:1.0283047;stroke-miterlimit:4;stroke-opacity:1"
-       d="M -0.99929609,42.004237 C 2.9290204,42.117701 4.1278823,38.950282 4.9828709,38.950282 C 5.8260957,38.950282 7.1161651,42.240122 10.014606,42.007796 C 9.2074596,43.955072 6.7265914,47.014858 5.6807127,47.014858 C 4.6230593,47.014858 0.31231911,44.880662 -0.99929609,42.004237 z "
-       id="rect5187"
-       sodipodi:nodetypes="ccczc" />
-    <path
-       transform="matrix(0.743268,0,0,0.267357,-7.659906,-1.671861)"
        style="fill:#3b1941;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 11.651119,11.193815 C 13.577759,8.2509126 16.249277,11.481501 17.614226,12.804399 L 14.761306,13.747613 L 11.651119,11.193815 z "
+       d="M -3.174544e-16,1.7837407 C 0.49897694,0.43045085 3.4176637,1.3941391 4.4321866,1.7478251 L 2.7448964,2 L -3.174544e-16,1.7837407 z "
        id="path5192"
        sodipodi:nodetypes="cccc" />
     <path
-       transform="matrix(0.686065,0,0,0.46633,-5.019573,-4.365629)"
-       style="fill:#3b1941;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 11.689238,9.8218679 C 13.591296,8.0161941 17.174576,11.994261 17.519594,13.650486 L 14.543472,12.891665 L 11.689238,9.8218679 z "
-       id="rect5189"
-       sodipodi:nodetypes="cccc" />
+       style="fill:#fcaf3e;fill-opacity:1;stroke:none;stroke-width:1.0283047;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 4,8.9694498 C 6.5363255,9.6796143 7.1434322,8 7.6676187,8 C 8.1845929,8 8.1150542,9.7216455 10.752536,9.1373864 C 10.257681,9.8617678 8.7366795,11 8.0954601,11 C 7.4470215,11 4.8041406,10.039472 4,8.9694498 z "
+       id="path3987"
+       sodipodi:nodetypes="czczc" />
     <path
-       transform="matrix(0.63556,0,0,0.371995,4.635112,-6.489295)"
-       style="fill:url(#linearGradient6823);fill-opacity:1;stroke:none;stroke-width:1.0283047;stroke-miterlimit:4;stroke-opacity:1"
-       d="M -0.99929609,42.004237 C 2.9290204,42.117701 4.1278823,38.950282 4.9828709,38.950282 C 5.8260957,38.950282 7.1161651,42.240122 10.014606,42.007796 C 9.2074596,43.955072 6.7265914,47.014858 5.6807127,47.014858 C 4.6230593,47.014858 0.31231911,44.880662 -0.99929609,42.004237 z "
-       id="path6815"
-       sodipodi:nodetypes="ccczc" />
+       style="fill:#3b1941;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 2.5678134,0.78213791 C 3.0667903,-0.57115198 7,-0.11652293 7,1.7459005 L 5.3127098,0.99839721 L 2.5678134,0.78213791 z "
+       id="path1991"
+       sodipodi:nodetypes="cccc" />
   </g>
 </svg>
Binary file pidgin/pixmaps/icons/24/pidgin.png has changed
--- a/pidgin/pixmaps/icons/24/scalable/pidgin.svg	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/icons/24/scalable/pidgin.svg	Mon Jun 18 01:48:35 2007 +0000
@@ -14,9 +14,9 @@
    id="svg4345"
    sodipodi:version="0.32"
    inkscape:version="0.44.1"
-   sodipodi:docbase="/home/hbons/Desktop/icons/24/scalable"
+   sodipodi:docbase="/home/hbons/Desktop/2.0.2/pidgin/pixmaps/icons/24/scalable"
    sodipodi:docname="pidgin.svg"
-   inkscape:export-filename="/home/hbons/Desktop/pidgin24-2.png"
+   inkscape:export-filename="/home/hbons/Desktop/pidgin24.png"
    inkscape:export-xdpi="90"
    inkscape:export-ydpi="90"
    version="1.0">
@@ -24,6 +24,42 @@
      id="defs4347">
     <linearGradient
        inkscape:collect="always"
+       id="linearGradient3124">
+      <stop
+         style="stop-color:#3b1941;stop-opacity:1;"
+         offset="0"
+         id="stop3126" />
+      <stop
+         style="stop-color:#3b1941;stop-opacity:0;"
+         offset="1"
+         id="stop3128" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3116">
+      <stop
+         style="stop-color:#82508e;stop-opacity:1;"
+         offset="0"
+         id="stop3118" />
+      <stop
+         style="stop-color:#82508e;stop-opacity:0;"
+         offset="1"
+         id="stop3120" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3108">
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:1;"
+         offset="0"
+         id="stop3110" />
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:0;"
+         offset="1"
+         id="stop3112" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
        id="linearGradient5438">
       <stop
          style="stop-color:white;stop-opacity:1;"
@@ -71,30 +107,6 @@
          id="stop6510" />
     </linearGradient>
     <linearGradient
-       inkscape:collect="always"
-       id="linearGradient5304">
-      <stop
-         style="stop-color:#2e3436;stop-opacity:1;"
-         offset="0"
-         id="stop5306" />
-      <stop
-         style="stop-color:#2e3436;stop-opacity:0;"
-         offset="1"
-         id="stop5308" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient5280">
-      <stop
-         style="stop-color:#82508e;stop-opacity:1;"
-         offset="0"
-         id="stop5282" />
-      <stop
-         style="stop-color:#82508e;stop-opacity:0;"
-         offset="1"
-         id="stop5284" />
-    </linearGradient>
-    <linearGradient
        id="linearGradient2804">
       <stop
          style="stop-color:black;stop-opacity:0;"
@@ -165,43 +177,14 @@
          offset="1.0000000"
          id="stop3804" />
     </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient5280"
-       id="radialGradient5286"
-       cx="15.004828"
-       cy="39.80859"
-       fx="15.004828"
-       fy="39.80859"
-       r="9.7225161"
-       gradientTransform="matrix(1,0,0,0.732283,0,10.65742)"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient5304"
-       id="linearGradient5310"
-       x1="12.606371"
-       y1="15.069461"
-       x2="12.606371"
-       y2="21.152372"
-       gradientUnits="userSpaceOnUse" />
     <linearGradient
        inkscape:collect="always"
        xlink:href="#linearGradient6506"
        id="linearGradient6512"
        x1="15.645709"
-       y1="39.743458"
+       y1="40.434063"
        x2="15.645709"
-       y2="53.502155"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6537"
-       id="linearGradient6543"
-       x1="30.5"
-       y1="0.033532728"
-       x2="30.5"
-       y2="23.559282"
+       y2="43.693668"
        gradientUnits="userSpaceOnUse" />
     <linearGradient
        inkscape:collect="always"
@@ -221,6 +204,250 @@
        x2="30.152058"
        y2="23.011967"
        gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="44.272076"
+       x2="5.5366187"
+       y1="39.902092"
+       x1="-1.6841649"
+       id="linearGradient6569"
+       xlink:href="#linearGradient6563"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="23.559282"
+       x2="30.5"
+       y1="0.033532728"
+       x1="30.5"
+       id="linearGradient2089"
+       xlink:href="#linearGradient6537"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="50.079575"
+       x2="14.943421"
+       y1="39.743458"
+       x1="15.645709"
+       id="linearGradient2087"
+       xlink:href="#linearGradient6506"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2081">
+      <stop
+         id="stop2083"
+         offset="0.0000000"
+         style="stop-color:#f4d9b1;stop-opacity:1.0000000;" />
+      <stop
+         id="stop2085"
+         offset="1.0000000"
+         style="stop-color:#df9725;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.131317,0,0,1.125313,-1.035262,-0.301139)"
+       r="8.4883642"
+       fy="2.6242435"
+       fx="7.8836637"
+       cy="2.6242435"
+       cx="7.8836637"
+       id="radialGradient2079"
+       xlink:href="#linearGradient25546"
+       inkscape:collect="always" />
+    <radialGradient
+       r="8.4883642"
+       fy="0.14505707"
+       fx="7.8836741"
+       cy="0.14505707"
+       cx="7.8836741"
+       gradientTransform="matrix(1,0,0,0.994693,0,4.16407e-2)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2071"
+       xlink:href="#linearGradient25546"
+       inkscape:collect="always" />
+    <radialGradient
+       r="8.4883642"
+       fy="1.5104795"
+       fx="7.8836637"
+       cy="1.5104795"
+       cx="7.8836637"
+       gradientTransform="matrix(1,0,0,0.994693,0,4.16407e-2)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2069"
+       xlink:href="#linearGradient25546"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2061">
+      <stop
+         id="stop2063"
+         offset="0"
+         style="stop-color:black;stop-opacity:0;" />
+      <stop
+         style="stop-color:black;stop-opacity:1;"
+         offset="0.5"
+         id="stop2065" />
+      <stop
+         id="stop2067"
+         offset="1"
+         style="stop-color:black;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient6563"
+       inkscape:collect="always">
+      <stop
+         id="stop6565"
+         offset="0"
+         style="stop-color:white;stop-opacity:1;" />
+      <stop
+         id="stop6567"
+         offset="1"
+         style="stop-color:white;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2850"
+       inkscape:collect="always">
+      <stop
+         id="stop2852"
+         offset="0"
+         style="stop-color:#ce5c00;stop-opacity:1;" />
+      <stop
+         id="stop2854"
+         offset="1"
+         style="stop-color:#ce5c00;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3958"
+       inkscape:collect="always">
+      <stop
+         id="stop3960"
+         offset="0"
+         style="stop-color:#eeeeec;stop-opacity:1;" />
+      <stop
+         id="stop3962"
+         offset="1"
+         style="stop-color:#eeeeec;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3968"
+       inkscape:collect="always">
+      <stop
+         id="stop3970"
+         offset="0"
+         style="stop-color:#82508e;stop-opacity:1;" />
+      <stop
+         id="stop3972"
+         offset="1"
+         style="stop-color:#82508e;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3976"
+       inkscape:collect="always">
+      <stop
+         id="stop3978"
+         offset="0"
+         style="stop-color:#3b1941;stop-opacity:1;" />
+      <stop
+         id="stop3980"
+         offset="1"
+         style="stop-color:#3b1941;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2850"
+       id="linearGradient2149"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.769231,0,0,0.714287,-34.23081,-12.28573)"
+       x1="21.785719"
+       y1="28.142857"
+       x2="17.785713"
+       y2="30.07143" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3958"
+       id="radialGradient2191"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.116159,0,0,1.076653,-36.39499,-20.28695)"
+       cx="9.0640488"
+       cy="21.511742"
+       fx="9.0640488"
+       fy="21.511742"
+       r="16.663956" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6506"
+       id="linearGradient2193"
+       gradientUnits="userSpaceOnUse"
+       x1="15.645709"
+       y1="39.743458"
+       x2="15.645709"
+       y2="53.502155"
+       gradientTransform="matrix(0.660903,0,0,0.627207,-32.26852,-10.3201)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3968"
+       id="linearGradient2196"
+       gradientUnits="userSpaceOnUse"
+       x1="16.13257"
+       y1="40.781811"
+       x2="16.13257"
+       y2="48.068741"
+       gradientTransform="matrix(0.67692,0,0,0.646801,-32.53568,-10.90841)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3976"
+       id="linearGradient2198"
+       gradientUnits="userSpaceOnUse"
+       x1="12.095973"
+       y1="40.907658"
+       x2="12.095973"
+       y2="46.463146"
+       gradientTransform="matrix(0.67692,0,0,0.646801,-32.53568,-10.90841)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6537"
+       id="linearGradient2201"
+       gradientUnits="userSpaceOnUse"
+       x1="30.5"
+       y1="0.033532728"
+       x2="30.5"
+       y2="23.559282"
+       gradientTransform="matrix(0.668893,0,0,0.668627,-32.91377,-10.19246)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3108"
+       id="linearGradient3114"
+       x1="10.18327"
+       y1="16.618088"
+       x2="27.598003"
+       y2="36.64465"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3116"
+       id="linearGradient3122"
+       x1="15.722902"
+       y1="39.585075"
+       x2="15.722902"
+       y2="45.76453"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3124"
+       id="linearGradient3130"
+       x1="13.150809"
+       y1="39.39394"
+       x2="13.150809"
+       y2="45.551888"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2850"
+       id="linearGradient3146"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.769231,0,0,0.714287,-3.230767,-7.285729)"
+       x1="21.785719"
+       y1="28.142857"
+       x2="17.785713"
+       y2="30.07143" />
   </defs>
   <sodipodi:namedview
      id="base"
@@ -229,17 +456,17 @@
      borderopacity="1.0"
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
-     inkscape:zoom="26.124924"
-     inkscape:cx="19.621039"
-     inkscape:cy="12.735051"
+     inkscape:zoom="16.081777"
+     inkscape:cx="21.855503"
+     inkscape:cy="14.873812"
      inkscape:current-layer="layer1"
      showgrid="true"
      inkscape:grid-bbox="true"
      inkscape:document-units="px"
-     inkscape:window-width="1274"
-     inkscape:window-height="966"
-     inkscape:window-x="3"
-     inkscape:window-y="25"
+     inkscape:window-width="1434"
+     inkscape:window-height="840"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
      showguides="true"
      inkscape:guide-bbox="true"
      inkscape:grid-points="false"
@@ -282,44 +509,21 @@
        transform="matrix(1.747787,0,0,1.397993,-52.41719,-5.183942)"
        sodipodi:nodetypes="csccccc" />
     <path
-       style="opacity:1;fill:#82508e;fill-opacity:1;stroke:#3b1941;stroke-width:1.51128328;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       style="opacity:1;fill:url(#linearGradient3122);fill-opacity:1.0;stroke:url(#linearGradient3130);stroke-width:1.51128328;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
        d="M 15,13 C 8.3759979,13 3,18.600001 3,25.5 C 3,31.153143 2.9750563,38.402618 2.9750563,45.572826 C 4.1625449,45.572826 27.946366,45.600605 30.637365,45.600605 C 32.751492,45.600605 32.586331,43.541005 32.586331,43.541005 C 32.586331,40.875594 27.597902,38.639057 25.813453,36.682531 C 23.985035,34.68151 26,30.5 26,30.5 C 26.641306,28.9702 27,27.275084 27,25.5 C 27,18.600001 21.624002,13 15,13 z "
        id="path5176"
        sodipodi:nodetypes="ccccszcsc"
        transform="matrix(0.67692,0,0,0.646801,-1.52611,-5.949693)" />
     <path
-       sodipodi:type="arc"
-       style="opacity:1;fill:url(#radialGradient5286);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path5273"
-       sodipodi:cx="15.004828"
-       sodipodi:cy="39.80859"
-       sodipodi:rx="9.7225161"
-       sodipodi:ry="7.119638"
-       d="M 24.727345 39.80859 A 9.7225161 7.119638 0 1 1  5.2823124,39.80859 A 9.7225161 7.119638 0 1 1  24.727345 39.80859 z"
-       transform="matrix(0.661428,0,0,0.760624,-1.973841,-10.20757)" />
-    <path
-       style="opacity:0.5152838;fill:#5c3466;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M -42.833794,49.038847 C -42.833794,49.038847 -42.815855,44.709724 -42.815855,37.951005 C -42.815855,37.951005 -39.03087,40.509965 -38.631892,41.678764 C -39.153711,41.596001 -40.372039,41.685633 -40.372039,41.685633 C -40.038351,42.463101 -38.163796,45.952105 -36.121045,48.058218 C -37.780497,47.329365 -39.471111,47.196178 -39.471111,47.196178 C -39.009636,48.111847 -37.250115,48.69173 -36.943887,49.110993 C -36.943887,49.110993 -41.348464,49.038847 -42.833794,49.038847 z "
-       id="rect5312"
-       sodipodi:nodetypes="cccccccc"
-       transform="matrix(0.799568,0,0,0.627241,35.24855,-7.804428)" />
-    <path
-       style="opacity:0.5152838;fill:#5c3466;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M -49.441852,47.4154 C -48.364983,40.273995 -40.690447,44.765623 -40.961409,37.951005 C -40.961409,37.951005 -39.025024,40.280009 -38.974466,41.581367 C -39.496285,41.498604 -39.881988,41.516405 -39.881988,41.516405 C -39.5483,42.293873 -38.196948,45.748112 -36.154197,47.854225 C -37.813649,47.125372 -38.925816,46.898039 -38.925816,46.898039 C -38.847603,47.794771 -38.376224,47.369394 -38.122982,48.215235 C -42.942294,48.046898 -46.252916,49.195571 -49.441852,47.4154 z "
-       id="path5317"
-       sodipodi:nodetypes="cccccccc"
-       transform="matrix(-0.602064,0,0,0.572779,-9.767144,-4.737575)" />
-    <path
        transform="matrix(0.660903,0,0,0.627207,-1.258953,-5.361383)"
-       style="opacity:0.31004363;fill:url(#linearGradient5310);fill-opacity:1;stroke:url(#linearGradient6512);stroke-width:1.55319395;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       style="opacity:0.5;fill:url(#linearGradient3114);fill-opacity:1.0;stroke:url(#linearGradient6512);stroke-width:1.55319395;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
        d="M 15,14.0625 C 8.9877035,14.0625 4.0789961,19.13808 4.0625,25.46875 C 4.0624722,25.479427 4.0617033,25.489349 4.0625,25.5 C 4.0625,32.787473 3.9033639,38.26012 3.9033639,44.499878 C 5.8399452,44.499878 22.452275,44.470084 28.278248,44.470084 C 29.445455,44.470084 31.431654,44.974157 31.431654,43.509594 C 31.431654,43.287851 31.231903,42.870917 30.681654,42.353344 C 30.131405,41.835771 29.308414,41.280003 28.400404,40.728344 C 26.665321,39.858723 25.411769,39.090553 24.621247,37.290844 C 24.011242,36.47675 23.731303,35.519763 23.676839,34.478344 C 23.622375,33.436925 24.107721,32.319635 24.224561,31.259594 C 24.458241,29.139511 24.96875,30.28125 24.96875,30.28125 C 24.98374,30.216952 25.004663,30.154183 25.03125,30.09375 C 25.618731,28.692346 25.9375,27.131297 25.9375,25.5 C 25.9375,19.154404 21.022436,14.0625 15,14.0625 z "
        id="path5241"
        sodipodi:nodetypes="cscccssccsscssc" />
     <path
-       transform="matrix(-0.861857,-0.809791,0.812609,-0.76352,-5.667036,37.33378)"
-       style="opacity:1;fill:#a46bb0;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 13.257119,24.626053 C 13.257119,26.227351 11.8279,27.316574 10.863875,27.316574 C 9.5428049,27.316574 8.4706318,26.01697 8.4706318,24.415672 C 8.4706318,23.024119 9.2055946,21.514771 10.526665,21.514771 C 11.847736,21.514771 13.257119,23.360971 13.257119,24.626053 z "
-       id="path5160"
+       style="fill:#a46bb0;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 3.072604,7.0864988 C 4.607952,5.4493238 7.105721,5.8854918 8.086061,6.9308478 C 9.4294869,8.3633698 9.273726,10.85472 7.738379,12.491894 C 6.404137,13.914624 4.209552,14.660821 2.866124,13.228299 C 1.522696,11.795776 1.859625,8.3799248 3.072604,7.0864988 z "
+       id="path3138"
        sodipodi:nodetypes="csssc" />
     <path
        transform="matrix(1.010846,0,0,1.029732,-5.552971,-15.17001)"
@@ -336,45 +540,7 @@
        sodipodi:rx="1.2410715"
        sodipodi:ry="1.2946428"
        d="M 11.410714 24.3125 A 1.2410715 1.2946428 0 1 1  8.928571,24.3125 A 1.2410715 1.2946428 0 1 1  11.410714 24.3125 z"
-       transform="matrix(0.805757,0,0,0.772415,-3.184731,-8.820615)" />
-    <path
-       transform="matrix(0.596326,-0.813274,-0.562251,-0.766804,22.42583,37.43862)"
-       style="opacity:1;fill:#975fa3;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 13.257119,24.626053 C 13.257119,26.227351 11.8279,27.316574 10.863875,27.316574 C 9.5428049,27.316574 8.4706318,26.01697 8.4706318,24.415672 C 8.4706318,23.024119 9.2055946,21.514771 10.526665,21.514771 C 11.847736,21.514771 13.257119,23.360971 13.257119,24.626053 z "
-       id="path5167"
-       sodipodi:nodetypes="csssc" />
-    <path
-       transform="matrix(0.447398,-0.672135,-0.421833,-0.633728,21.07418,32.19024)"
-       style="opacity:1;fill:white;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 13.257119,24.626053 C 13.257119,26.227351 11.8279,27.316574 10.863875,27.316574 C 9.5428049,27.316574 8.4706318,26.01697 8.4706318,24.415672 C 8.4706318,23.024119 9.2055946,21.514771 10.526665,21.514771 C 11.847736,21.514771 13.257119,23.360971 13.257119,24.626053 z "
-       id="path5169"
-       sodipodi:nodetypes="csssc" />
-    <path
-       sodipodi:type="arc"
-       style="opacity:1;fill:#5c3566;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path5171"
-       sodipodi:cx="10.169642"
-       sodipodi:cy="24.3125"
-       sodipodi:rx="1.2410715"
-       sodipodi:ry="1.2946428"
-       d="M 11.410714 24.3125 A 1.2410715 1.2946428 0 1 1  8.928571,24.3125 A 1.2410715 1.2946428 0 1 1  11.410714 24.3125 z"
-       transform="matrix(0.805756,0,0,0.784291,6.815275,-9.124735)" />
-    <rect
-       style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="rect5215"
-       width="5.6071429"
-       height="2.1785715"
-       x="16"
-       y="27"
-       transform="matrix(0.724348,0,0,0.459012,-2.641559,0.565398)"
-       rx="0.87366539"
-       ry="1.0892857" />
-    <path
-       transform="matrix(0.798987,0,0,0.495994,7.007995,-6.360384)"
-       style="fill:#f9751a;fill-opacity:1;stroke:none;stroke-width:1.0283047;stroke-miterlimit:4;stroke-opacity:1"
-       d="M -0.99929609,42.004237 C 2.9290204,42.117701 4.1278823,38.950282 4.9828709,38.950282 C 5.8260957,38.950282 7.1161651,42.240122 10.014606,42.007796 C 9.2074596,43.955072 6.7265914,47.014858 5.6807127,47.014858 C 4.6230593,47.014858 0.31231911,44.880662 -0.99929609,42.004237 z "
-       id="rect5187"
-       sodipodi:nodetypes="ccczc" />
+       transform="matrix(1.208633,0,0,1.158621,-6.791366,-17.66897)" />
     <path
        transform="matrix(0.670792,0,0,0.486348,-3.805943,-3.90166)"
        style="fill:#3b1941;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
@@ -387,11 +553,53 @@
        d="M 11.689238,9.8218679 C 13.591296,8.0161941 17.174576,11.994261 17.519594,13.650486 L 14.543472,12.891665 L 11.689238,9.8218679 z "
        id="rect5189"
        sodipodi:nodetypes="cccc" />
+    <rect
+       style="opacity:0.23144106;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect3034"
+       width="36.000004"
+       height="2.9999979"
+       x="-84.444725"
+       y="32.42485"
+       rx="2.0412357"
+       ry="1.4999989" />
     <path
-       transform="matrix(0.798987,0,0,0.495994,7.007995,-6.360384)"
-       style="fill:url(#linearGradient6823);fill-opacity:1;stroke:none;stroke-width:1.0283047;stroke-miterlimit:4;stroke-opacity:1"
-       d="M -0.99929609,42.004237 C 2.9290204,42.117701 4.1278823,38.950282 4.9828709,38.950282 C 5.8260957,38.950282 7.1161651,42.240122 10.014606,42.007796 C 9.2074596,43.955072 6.7265914,47.014858 5.6807127,47.014858 C 4.6230593,47.014858 0.31231911,44.880662 -0.99929609,42.004237 z "
-       id="path6815"
-       sodipodi:nodetypes="ccczc" />
+       style="fill:#975fa3;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 16.371022,7.8148748 C 15.47069,6.586993 14.005993,6.9141191 13.43112,7.6981356 C 12.643332,8.7725276 12.734671,10.64104 13.635002,11.868921 C 14.417404,12.93597 15.704314,13.495617 16.492103,12.421225 C 17.279892,11.346833 17.082315,8.7849447 16.371022,7.8148748 z "
+       id="path3132"
+       sodipodi:nodetypes="csssc" />
+    <path
+       style="fill:white;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 16.502957,8.5432477 C 15.827476,7.7246593 14.728576,7.9427464 14.297274,8.4654263 C 13.706229,9.1816906 13.774757,10.427368 14.450238,11.245957 C 15.037241,11.957323 16.002754,12.33042 16.593798,11.614156 C 17.184843,10.897891 17.03661,9.1899614 16.502957,8.5432477 z "
+       id="path3134"
+       sodipodi:nodetypes="csssc" />
+    <path
+       sodipodi:type="arc"
+       style="fill:#5c3566;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="path3136"
+       sodipodi:cx="10.169642"
+       sodipodi:cy="24.3125"
+       sodipodi:rx="1.2410715"
+       sodipodi:ry="1.2946428"
+       d="M 11.410714 24.3125 A 1.2410715 1.2946428 0 1 1  8.928571,24.3125 A 1.2410715 1.2946428 0 1 1  11.410714 24.3125 z"
+       transform="matrix(1.153827,0,0,1.158621,3.593156,-17.66895)" />
+    <rect
+       style="fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect3140"
+       width="4.4400907"
+       height="1"
+       x="8.5358553"
+       y="13"
+       rx="0.69182354"
+       ry="0.5" />
+    <path
+       style="fill:#fcaf3e;fill-opacity:1;stroke:none;stroke-width:1.0283047;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 6,13.893438 C 11.088512,17.243015 10.655188,12 11.431469,12 C 12.197069,12 11.699301,17.201991 16,13.895644 C 15.267157,15.102946 13.014668,17 12.06507,17 C 11.104781,17 7.190872,15.676807 6,13.893438 z "
+       id="path3142"
+       sodipodi:nodetypes="czczc" />
+    <path
+       style="fill:url(#linearGradient3146);fill-opacity:1;stroke:none;stroke-width:1.0283047;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 6,13.893439 C 10.740404,18.171305 10.655188,12 11.431469,12 C 12.197069,12 11.641283,17.027939 16,13.895646 C 15.267157,15.102947 13.014668,17 12.06507,17 C 11.104781,17 7.190873,15.676809 6,13.893439 z "
+       id="path3144"
+       sodipodi:nodetypes="czczc" />
   </g>
 </svg>
Binary file pidgin/pixmaps/icons/32/pidgin.png has changed
--- a/pidgin/pixmaps/icons/32/scalable/pidgin.svg	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/icons/32/scalable/pidgin.svg	Mon Jun 18 01:48:35 2007 +0000
@@ -14,9 +14,9 @@
    id="svg4345"
    sodipodi:version="0.32"
    inkscape:version="0.44.1"
-   sodipodi:docbase="/home/hbons/code/pidgin-mtn/pidgin/pixmaps/icons/32/scalable"
+   sodipodi:docbase="/home/hbons/Desktop/2.0.2/pidgin/pixmaps/icons/32/scalable"
    sodipodi:docname="pidgin.svg"
-   inkscape:export-filename="/home/hbons/code/pidgin-mtn/pidgin/pixmaps/icons/32/pidgin.png"
+   inkscape:export-filename="/home/hbons/Desktop/pidgin32.png"
    inkscape:export-xdpi="90"
    inkscape:export-ydpi="90"
    version="1.0">
@@ -24,18 +24,131 @@
      id="defs4347">
     <linearGradient
        inkscape:collect="always"
-       id="linearGradient6817">
+       id="linearGradient3976">
+      <stop
+         style="stop-color:#3b1941;stop-opacity:1;"
+         offset="0"
+         id="stop3978" />
+      <stop
+         style="stop-color:#3b1941;stop-opacity:0;"
+         offset="1"
+         id="stop3980" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3968">
+      <stop
+         style="stop-color:#82508e;stop-opacity:1;"
+         offset="0"
+         id="stop3970" />
+      <stop
+         style="stop-color:#82508e;stop-opacity:0;"
+         offset="1"
+         id="stop3972" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3958">
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:1;"
+         offset="0"
+         id="stop3960" />
       <stop
-         style="stop-color:white;stop-opacity:1;"
+         style="stop-color:#eeeeec;stop-opacity:0;"
+         offset="1"
+         id="stop3962" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2850">
+      <stop
+         style="stop-color:#ce5c00;stop-opacity:1;"
+         offset="0"
+         id="stop2852" />
+      <stop
+         style="stop-color:#ce5c00;stop-opacity:0;"
+         offset="1"
+         id="stop2854" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2850"
+       id="linearGradient2856"
+       x1="21.785719"
+       y1="28.142857"
+       x2="17.785713"
+       y2="30.07143"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-47,-15.99998)" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2816">
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:1;"
          offset="0"
-         id="stop6819" />
+         id="stop2818" />
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:0;"
+         offset="1"
+         id="stop2820" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2816"
+       id="radialGradient2824"
+       cx="9.4288578"
+       cy="19.283415"
+       fx="9.4288578"
+       fy="19.283415"
+       r="16.390338"
+       gradientTransform="matrix(1.556432,0,0,1.618148,-52.04294,-30.39321)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2826">
+      <stop
+         style="stop-color:#3b1941;stop-opacity:1;"
+         offset="0"
+         id="stop2828" />
       <stop
-         style="stop-color:white;stop-opacity:0;"
+         style="stop-color:#3b1941;stop-opacity:0;"
          offset="1"
-         id="stop6821" />
+         id="stop2830" />
     </linearGradient>
     <linearGradient
        inkscape:collect="always"
+       xlink:href="#linearGradient2826"
+       id="linearGradient2832"
+       x1="13.191773"
+       y1="41.606163"
+       x2="13.191773"
+       y2="47.843258"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.988192,-46.55265,-16.48621)" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2834">
+      <stop
+         style="stop-color:#82508e;stop-opacity:1;"
+         offset="0"
+         id="stop2836" />
+      <stop
+         style="stop-color:#82508e;stop-opacity:0;"
+         offset="1"
+         id="stop2838" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2834"
+       id="linearGradient2840"
+       x1="11.373499"
+       y1="41.566242"
+       x2="11.373499"
+       y2="47.746658"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.988192,-46.55265,-16.48621)" />
+    <linearGradient
+       inkscape:collect="always"
        id="linearGradient6563">
       <stop
          style="stop-color:white;stop-opacity:1;"
@@ -71,30 +184,6 @@
          id="stop6510" />
     </linearGradient>
     <linearGradient
-       inkscape:collect="always"
-       id="linearGradient5304">
-      <stop
-         style="stop-color:#2e3436;stop-opacity:1;"
-         offset="0"
-         id="stop5306" />
-      <stop
-         style="stop-color:#2e3436;stop-opacity:0;"
-         offset="1"
-         id="stop5308" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient5280">
-      <stop
-         style="stop-color:#82508e;stop-opacity:1;"
-         offset="0"
-         id="stop5282" />
-      <stop
-         style="stop-color:#82508e;stop-opacity:0;"
-         offset="1"
-         id="stop5284" />
-    </linearGradient>
-    <linearGradient
        id="linearGradient2804">
       <stop
          style="stop-color:black;stop-opacity:0;"
@@ -165,34 +254,14 @@
          offset="1.0000000"
          id="stop3804" />
     </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient5280"
-       id="radialGradient5286"
-       cx="15.004828"
-       cy="39.80859"
-       fx="15.004828"
-       fy="39.80859"
-       r="9.7225161"
-       gradientTransform="matrix(1,0,0,0.732283,0,10.65742)"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient5304"
-       id="linearGradient5310"
-       x1="12.606371"
-       y1="15.069461"
-       x2="12.606371"
-       y2="21.152372"
-       gradientUnits="userSpaceOnUse" />
     <linearGradient
        inkscape:collect="always"
        xlink:href="#linearGradient6506"
        id="linearGradient6512"
        x1="15.645709"
        y1="39.743458"
-       x2="15.645709"
-       y2="53.502155"
+       x2="14.943421"
+       y2="50.079575"
        gradientUnits="userSpaceOnUse" />
     <linearGradient
        inkscape:collect="always"
@@ -214,13 +283,62 @@
        gradientUnits="userSpaceOnUse" />
     <linearGradient
        inkscape:collect="always"
-       xlink:href="#linearGradient6817"
-       id="linearGradient6823"
-       x1="0.23931108"
-       y1="38.950283"
-       x2="5.7089725"
-       y2="42.982571"
+       xlink:href="#linearGradient6537"
+       id="linearGradient3069"
+       gradientUnits="userSpaceOnUse"
+       x1="30.5"
+       y1="0.033532728"
+       x2="30.5"
+       y2="23.559282" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6506"
+       id="linearGradient3071"
+       gradientUnits="userSpaceOnUse"
+       x1="15.645709"
+       y1="39.743458"
+       x2="15.645709"
+       y2="53.502155"
+       gradientTransform="translate(-47,-15)" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3958"
+       id="radialGradient3966"
+       cx="9.0640488"
+       cy="21.511742"
+       fx="9.0640488"
+       fy="21.511742"
+       r="16.663956"
+       gradientTransform="matrix(1.68884,0,0,1.716583,-6.243689,-15.89085)"
        gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3968"
+       id="linearGradient3974"
+       x1="16.13257"
+       y1="40.781811"
+       x2="16.13257"
+       y2="48.068741"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3976"
+       id="linearGradient3982"
+       x1="12.095973"
+       y1="40.907658"
+       x2="12.095973"
+       y2="46.463146"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2850"
+       id="linearGradient3991"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.769231,0,0,0.714287,-1.230773,-2.285726)"
+       x1="21.785719"
+       y1="28.142857"
+       x2="17.785713"
+       y2="30.07143" />
   </defs>
   <sodipodi:namedview
      id="base"
@@ -229,17 +347,17 @@
      borderopacity="1.0"
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
-     inkscape:zoom="21.220032"
-     inkscape:cx="25.558911"
-     inkscape:cy="16.91503"
+     inkscape:zoom="17.236022"
+     inkscape:cx="21.944662"
+     inkscape:cy="16.287609"
      inkscape:current-layer="layer1"
      showgrid="true"
      inkscape:grid-bbox="true"
      inkscape:document-units="px"
-     inkscape:window-width="1274"
-     inkscape:window-height="966"
-     inkscape:window-x="3"
-     inkscape:window-y="25"
+     inkscape:window-width="1434"
+     inkscape:window-height="840"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
      showguides="true"
      inkscape:guide-bbox="true"
      inkscape:grid-points="false"
@@ -261,16 +379,6 @@
      id="layer1"
      inkscape:label="Layer 1"
      inkscape:groupmode="layer">
-    <rect
-       style="opacity:0.23144106;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="rect6514"
-       width="5.0217423"
-       height="5.2252574"
-       x="42.978256"
-       y="44"
-       rx="0.28473777"
-       ry="2.6126287"
-       transform="matrix(4.779203,0,0,0.382753,-205.4017,13.15888)" />
     <path
        sodipodi:type="inkscape:offset"
        inkscape:radius="-1.0057179"
@@ -292,51 +400,28 @@
        id="path6535"
        sodipodi:nodetypes="cccccccccccccc" />
     <path
-       style="opacity:1;fill:#82508e;fill-opacity:1;stroke:#3b1941;stroke-width:1.51128328;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       style="opacity:1;fill:url(#linearGradient3974);fill-opacity:1.0;stroke:url(#linearGradient3982);stroke-width:1.51128328;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
        d="M 15,13 C 8.3759979,13 3,18.600001 3,25.5 C 4.8460021,40.483064 0.49299658,38.484005 0.052646307,45.33795 C 0.052646307,47.422072 1.0380664,48.413461 3.1446965,48.413461 C 4.3321851,48.413461 29.360035,48.5596 32.051034,48.5596 C 34.165161,48.5596 34,46.5 34,46.5 C 34,43.834589 27.597902,41.598052 25.813453,39.641526 C 23.985035,37.640505 26,30.5 26,30.5 C 26.641306,28.9702 27,27.275084 27,25.5 C 27,18.600001 21.624002,13 15,13 z "
        id="path5176"
        sodipodi:nodetypes="cccccszcsc"
        transform="matrix(0.67692,0,0,0.646801,0.464358,-0.908413)" />
     <path
-       sodipodi:type="arc"
-       style="opacity:1;fill:url(#radialGradient5286);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path5273"
-       sodipodi:cx="15.004828"
-       sodipodi:cy="39.80859"
-       sodipodi:rx="9.7225161"
-       sodipodi:ry="7.119638"
-       d="M 24.727345 39.80859 A 9.7225161 7.119638 0 1 1  5.2823124,39.80859 A 9.7225161 7.119638 0 1 1  24.727345 39.80859 z"
-       transform="matrix(0.661428,0,0,0.760624,1.662895e-2,-5.166292)" />
-    <path
-       style="opacity:0.5152838;fill:#5c3466;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M -42.833794,47.629347 C -42.833794,47.629347 -43.26687,44.687985 -40.223294,37.951005 C -40.223294,37.951005 -39.03087,40.509965 -38.631892,41.678764 C -39.153711,41.596001 -40.372039,41.685633 -40.372039,41.685633 C -40.038351,42.463101 -38.163796,45.952105 -36.121045,48.058218 C -37.780497,47.329365 -39.471111,47.196178 -39.471111,47.196178 C -39.009636,48.111847 -37.250115,48.69173 -36.943887,49.110993 C -36.943887,49.110993 -42.597127,49.864236 -42.833794,47.629347 z "
-       id="rect5312"
-       sodipodi:nodetypes="cccccccc"
-       transform="matrix(0.797045,0,0,0.733236,35.01127,-5.421684)" />
-    <path
-       style="opacity:0.5152838;fill:#5c3466;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M -49.441852,47.4154 C -48.364983,40.273995 -40.690447,44.765623 -40.961409,37.951005 C -40.961409,37.951005 -39.025024,40.280009 -38.974466,41.581367 C -39.496285,41.498604 -39.881988,41.516405 -39.881988,41.516405 C -39.5483,42.293873 -38.196948,45.748112 -36.154197,47.854225 C -37.813649,47.125372 -38.925816,46.898039 -38.925816,46.898039 C -38.847603,47.794771 -38.376224,47.369394 -38.122982,48.215235 C -42.942294,48.046898 -46.252916,49.195571 -49.441852,47.4154 z "
-       id="path5317"
-       sodipodi:nodetypes="cccccccc"
-       transform="matrix(-0.724368,0,0,0.660383,-12.52413,-1.979892)" />
-    <path
-       transform="matrix(0.660903,0,0,0.627207,0.731515,-0.320103)"
-       style="opacity:0.31004363;fill:url(#linearGradient5310);fill-opacity:1;stroke:url(#linearGradient6512);stroke-width:1.55319357;stroke-miterlimit:4;stroke-opacity:1"
+       style="opacity:0.5;fill:url(#radialGradient3966);fill-opacity:1.0;stroke:url(#linearGradient6512);stroke-width:1.55319357;stroke-miterlimit:4;stroke-opacity:1"
        d="M 15,14.0625 C 8.9877035,14.0625 4.0789961,19.13808 4.0625,25.46875 C 4.0624722,25.479427 4.0625,25.489316 4.0625,25.5 C 4.9744187,33.020507 4.3062656,37.469969 2.59375,40.59375 C -0.19778709,46.24536 1.5610206,47.490284 3.9033639,47.490284 C 5.8399452,47.490284 23.958121,47.46049 29.784094,47.46049 C 30.951301,47.46049 32.9375,47.964563 32.9375,46.5 C 32.9375,46.278257 32.737749,45.861323 32.1875,45.34375 C 31.637251,44.826177 30.81426,44.270409 29.90625,43.71875 C 28.99824,43.167091 28.02821,42.609033 27.15625,42.0625 C 26.28429,41.515967 25.511654,41.005793 24.96875,40.28125 C 24.358745,39.467156 24.078806,38.510169 24.024342,37.46875 C 23.969878,36.427331 24.107721,35.310041 24.224561,34.25 C 24.458241,32.129917 24.96875,30.28125 24.96875,30.28125 C 24.98374,30.216952 25.004663,30.154183 25.03125,30.09375 C 25.618731,28.692346 25.9375,27.131297 25.9375,25.5 C 25.9375,19.154404 21.022436,14.0625 15,14.0625 z "
        id="path5241"
-       sodipodi:nodetypes="csscccssssssscssc" />
+       sodipodi:nodetypes="csscccssssssscssc"
+       transform="matrix(0.660903,0,0,0.627207,0.731515,-0.320103)" />
     <path
-       transform="matrix(-0.861857,-0.809791,0.812609,-0.76352,-3.676568,42.37505)"
        style="opacity:1;fill:#a46bb0;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 13.257119,24.626053 C 13.257119,26.227351 11.8279,27.316574 10.863875,27.316574 C 9.5428049,27.316574 8.4706318,26.01697 8.4706318,24.415672 C 8.4706318,23.024119 9.2055946,21.514771 10.526665,21.514771 C 11.847736,21.514771 13.257119,23.360971 13.257119,24.626053 z "
+       d="M 5.0726004,12.086499 C 6.6079483,10.449324 9.1057173,10.885492 10.086057,11.930848 C 11.429483,13.36337 11.273722,15.85472 9.7383746,17.491894 C 8.4041332,18.914624 6.2095475,19.660821 4.8661202,18.228299 C 3.5226923,16.795776 3.8596213,13.379925 5.0726004,12.086499 z "
        id="path5160"
        sodipodi:nodetypes="csssc" />
     <path
-       transform="matrix(1.010846,0,0,1.029732,-3.562503,-10.12874)"
        style="opacity:1;fill:white;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
        d="M 13.257119,24.626053 C 13.257119,26.227351 11.8279,27.316574 10.863875,27.316574 C 9.5428049,27.316574 8.4706318,26.01697 8.4706318,24.415672 C 8.4706318,23.024119 9.2055946,21.514771 10.526665,21.514771 C 11.847736,21.514771 13.257119,23.360971 13.257119,24.626053 z "
        id="path5157"
-       sodipodi:nodetypes="csssc" />
+       sodipodi:nodetypes="csssc"
+       transform="matrix(1.010846,0,0,1.029732,-3.562503,-10.12874)" />
     <path
        sodipodi:type="arc"
        style="opacity:1;fill:#5c3566;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
@@ -346,7 +431,7 @@
        sodipodi:rx="1.2410715"
        sodipodi:ry="1.2946428"
        d="M 11.410714 24.3125 A 1.2410715 1.2946428 0 1 1  8.928571,24.3125 A 1.2410715 1.2946428 0 1 1  11.410714 24.3125 z"
-       transform="matrix(0.805757,0,0,0.772415,-1.194263,-3.779337)" />
+       transform="matrix(1.208633,0,0,1.158621,-4.791365,-12.66897)" />
     <path
        transform="matrix(0.596326,-0.813274,-0.562251,-0.766804,24.4163,42.47989)"
        style="opacity:1;fill:#975fa3;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
@@ -354,11 +439,11 @@
        id="path5167"
        sodipodi:nodetypes="csssc" />
     <path
-       transform="matrix(0.447398,-0.542185,-0.421833,-0.511203,23.06465,33.31996)"
        style="opacity:1;fill:white;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
        d="M 13.257119,24.626053 C 13.257119,26.227351 11.8279,27.316574 10.863875,27.316574 C 9.5428049,27.316574 8.4706318,26.01697 8.4706318,24.415672 C 8.4706318,23.024119 9.2055946,21.514771 10.526665,21.514771 C 11.847736,21.514771 13.257119,23.360971 13.257119,24.626053 z "
        id="path5169"
-       sodipodi:nodetypes="csssc" />
+       sodipodi:nodetypes="csssc"
+       transform="matrix(0.447398,-0.542185,-0.421833,-0.511203,23.06465,33.31996)" />
     <path
        sodipodi:type="arc"
        style="opacity:1;fill:#5c3566;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
@@ -368,23 +453,16 @@
        sodipodi:rx="1.2410715"
        sodipodi:ry="1.2946428"
        d="M 11.410714 24.3125 A 1.2410715 1.2946428 0 1 1  8.928571,24.3125 A 1.2410715 1.2946428 0 1 1  11.410714 24.3125 z"
-       transform="matrix(0.805756,0,0,0.784291,8.805745,-4.083452)" />
+       transform="matrix(1.208633,0,0,1.158621,5.208632,-12.66896)" />
     <rect
        style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
        id="rect5215"
-       width="5.6071429"
-       height="2.1785715"
-       x="16"
-       y="27"
-       transform="matrix(0.724348,0,0,0.459012,-0.651091,5.606678)"
-       rx="0.87366539"
-       ry="1.0892857" />
-    <path
-       transform="matrix(0.798987,0,0,0.495994,8.99846,-1.319104)"
-       style="fill:#f9751a;fill-opacity:1;stroke:none;stroke-width:1.0283047;stroke-miterlimit:4;stroke-opacity:1"
-       d="M -0.99929609,42.004237 C 2.9290204,42.117701 4.1278823,38.950282 4.9828709,38.950282 C 5.8260957,38.950282 7.1161651,42.240122 10.014606,42.007796 C 9.2074596,43.955072 6.7265914,47.014858 5.6807127,47.014858 C 4.6230593,47.014858 0.31231911,44.880662 -0.99929609,42.004237 z "
-       id="rect5187"
-       sodipodi:nodetypes="ccczc" />
+       width="4.4400907"
+       height="1"
+       x="10.535856"
+       y="18"
+       rx="0.69182354"
+       ry="0.5" />
     <path
        transform="matrix(0.670792,0,0,0.486348,-1.815475,1.13962)"
        style="fill:#3b1941;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
@@ -398,10 +476,14 @@
        id="rect5189"
        sodipodi:nodetypes="cccc" />
     <path
-       transform="matrix(0.798987,0,0,0.495994,8.99846,-1.319104)"
-       style="fill:url(#linearGradient6823);fill-opacity:1.0;stroke:none;stroke-width:1.0283047;stroke-miterlimit:4;stroke-opacity:1"
-       d="M -0.99929609,42.004237 C 2.9290204,42.117701 4.1278823,38.950282 4.9828709,38.950282 C 5.8260957,38.950282 7.1161651,42.240122 10.014606,42.007796 C 9.2074596,43.955072 6.7265914,47.014858 5.6807127,47.014858 C 4.6230593,47.014858 0.31231911,44.880662 -0.99929609,42.004237 z "
-       id="path6815"
-       sodipodi:nodetypes="ccczc" />
+       style="fill:#fcaf3e;fill-opacity:1;stroke:none;stroke-width:1.0283047;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 8,18.893438 C 13.088512,22.243015 12.655188,17 13.431469,17 C 14.197069,17 13.699301,22.201991 18,18.895644 C 17.267157,20.102946 15.014668,22 14.06507,22 C 13.104781,22 9.1908718,20.676807 8,18.893438 z "
+       id="path3987"
+       sodipodi:nodetypes="czczc" />
+    <path
+       style="fill:url(#linearGradient3991);fill-opacity:1;stroke:none;stroke-width:1.0283047;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 8,18.893439 C 12.740404,23.171305 12.655188,17 13.431469,17 C 14.197069,17 13.641283,22.027939 18,18.895646 C 17.267157,20.102947 15.014668,22 14.06507,22 C 13.104781,22 9.1908731,20.676809 8,18.893439 z "
+       id="path3989"
+       sodipodi:nodetypes="czczc" />
   </g>
 </svg>
Binary file pidgin/pixmaps/icons/48/pidgin.png has changed
--- a/pidgin/pixmaps/icons/48/scalable/pidgin.svg	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/icons/48/scalable/pidgin.svg	Mon Jun 18 01:48:35 2007 +0000
@@ -14,15 +14,63 @@
    id="svg4345"
    sodipodi:version="0.32"
    inkscape:version="0.44.1"
-   sodipodi:docbase="/home/hbons/Desktop/icons/48/scalable"
+   sodipodi:docbase="/home/hbons/Desktop/2.0.2/pidgin/pixmaps/icons/48/scalable"
    sodipodi:docname="pidgin.svg"
-   inkscape:export-filename="/home/hbons/Desktop/pidgin.png"
+   inkscape:export-filename="/home/hbons/Desktop/pidgin48.png"
    inkscape:export-xdpi="90"
    inkscape:export-ydpi="90">
   <defs
      id="defs4347">
     <linearGradient
        inkscape:collect="always"
+       id="linearGradient2850">
+      <stop
+         style="stop-color:#ce5c00;stop-opacity:1;"
+         offset="0"
+         id="stop2852" />
+      <stop
+         style="stop-color:#ce5c00;stop-opacity:0;"
+         offset="1"
+         id="stop2854" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2834">
+      <stop
+         style="stop-color:#82508e;stop-opacity:1;"
+         offset="0"
+         id="stop2836" />
+      <stop
+         style="stop-color:#82508e;stop-opacity:0;"
+         offset="1"
+         id="stop2838" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2826">
+      <stop
+         style="stop-color:#3b1941;stop-opacity:1;"
+         offset="0"
+         id="stop2828" />
+      <stop
+         style="stop-color:#3b1941;stop-opacity:0;"
+         offset="1"
+         id="stop2830" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2816">
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:1;"
+         offset="0"
+         id="stop2818" />
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:0;"
+         offset="1"
+         id="stop2820" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
        id="linearGradient6563">
       <stop
          style="stop-color:white;stop-opacity:1;"
@@ -71,18 +119,6 @@
     </linearGradient>
     <linearGradient
        inkscape:collect="always"
-       id="linearGradient5304">
-      <stop
-         style="stop-color:#2e3436;stop-opacity:1;"
-         offset="0"
-         id="stop5306" />
-      <stop
-         style="stop-color:#2e3436;stop-opacity:0;"
-         offset="1"
-         id="stop5308" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
        id="linearGradient5280">
       <stop
          style="stop-color:#82508e;stop-opacity:1;"
@@ -177,15 +213,6 @@
        gradientUnits="userSpaceOnUse" />
     <linearGradient
        inkscape:collect="always"
-       xlink:href="#linearGradient5304"
-       id="linearGradient5310"
-       x1="12.606371"
-       y1="15.069461"
-       x2="12.606371"
-       y2="23.043955"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
        xlink:href="#linearGradient6493"
        id="linearGradient6499"
        x1="3.3105288"
@@ -198,27 +225,19 @@
        xlink:href="#linearGradient6506"
        id="linearGradient6512"
        x1="15.645709"
-       y1="39.743458"
+       y1="41.751736"
        x2="15.645709"
-       y2="53.502155"
-       gradientUnits="userSpaceOnUse" />
+       y2="47.370037"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.988192,0.5625,-1.39645)" />
     <linearGradient
        inkscape:collect="always"
        xlink:href="#linearGradient6537"
        id="linearGradient6543"
        x1="30.5"
-       y1="0.033532728"
+       y1="5.7732024"
        x2="30.5"
-       y2="23.559282"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient6563"
-       id="linearGradient6569"
-       x1="-1.6841649"
-       y1="39.902092"
-       x2="5.5366187"
-       y2="44.272076"
+       y2="19.518673"
        gradientUnits="userSpaceOnUse" />
     <linearGradient
        inkscape:collect="always"
@@ -229,6 +248,45 @@
        y1="38.950283"
        x2="5.5366187"
        y2="44.272076" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2816"
+       id="radialGradient2824"
+       cx="9.4288578"
+       cy="19.283415"
+       fx="9.4288578"
+       fy="19.283415"
+       r="16.390338"
+       gradientTransform="matrix(1.556432,0,0,1.618148,-5.04294,-15.39321)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2826"
+       id="linearGradient2832"
+       x1="13.191773"
+       y1="41.606163"
+       x2="13.191773"
+       y2="47.843258"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2834"
+       id="linearGradient2840"
+       x1="11.373499"
+       y1="41.566242"
+       x2="11.373499"
+       y2="47.746658"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2850"
+       id="linearGradient2856"
+       x1="21.785719"
+       y1="28.142857"
+       x2="17.785713"
+       y2="30.07143"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(0,-0.999982)" />
   </defs>
   <sodipodi:namedview
      id="base"
@@ -237,17 +295,17 @@
      borderopacity="1.0"
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
-     inkscape:zoom="1.1545694"
-     inkscape:cx="31.681369"
-     inkscape:cy="18.601404"
+     inkscape:zoom="14"
+     inkscape:cx="34.459692"
+     inkscape:cy="22.220728"
      inkscape:current-layer="layer1"
      showgrid="true"
      inkscape:grid-bbox="true"
      inkscape:document-units="px"
-     inkscape:window-width="1274"
-     inkscape:window-height="966"
-     inkscape:window-x="3"
-     inkscape:window-y="25"
+     inkscape:window-width="1434"
+     inkscape:window-height="840"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
      showguides="true"
      inkscape:guide-bbox="true"
      inkscape:grid-points="true" />
@@ -267,15 +325,14 @@
      inkscape:label="Layer 1"
      inkscape:groupmode="layer">
     <rect
-       style="opacity:0.23144105;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       style="opacity:0.23144106;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
        id="rect6514"
-       width="5.0217423"
-       height="5.2252574"
-       x="42.978256"
-       y="44"
-       rx="0.28473777"
-       ry="2.6126287"
-       transform="matrix(7.168827,0,0,0.574134,-308.1037,19.73808)" />
+       width="36.000004"
+       height="2.9999979"
+       x="-4.4446878"
+       y="57.424854"
+       rx="2.0412357"
+       ry="1.4999989" />
     <path
        sodipodi:type="inkscape:offset"
        inkscape:radius="-1.0057179"
@@ -296,43 +353,19 @@
        id="path6535"
        d="M 20.53125,2.53125 C 17.841732,2.53125 15.53125,5.0973912 15.53125,8.46875 L 15.53125,20.53125 C 15.53125,23.902609 17.841732,26.46875 20.53125,26.46875 L 34.53125,26.46875 C 35.097743,26.476048 35.555202,26.933507 35.5625,27.5 L 35.5625,29 L 38.71875,26.65625 C 38.901723,26.528628 39.120742,26.462922 39.34375,26.46875 L 41.5,26.46875 C 43.235888,26.46875 44.009537,25.921608 44.59375,24.9375 C 45.177963,23.953392 45.46875,22.367968 45.46875,20.53125 L 45.46875,8.46875 C 45.46875,5.0973915 43.158268,2.53125 40.46875,2.53125 L 20.53125,2.53125 z " />
     <path
-       style="opacity:1;fill:#82508e;fill-opacity:1;stroke:#3b1941;stroke-width:1.00595677;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       style="opacity:1;fill:url(#linearGradient2840);fill-opacity:1.0;stroke:url(#linearGradient2832);stroke-width:1.00595677;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
        d="M 15,13 C 8.3759979,13 3,18.600001 3,25.5 C 4.8460021,40.483064 0.49299658,38.484005 0.052646307,45.33795 C 0.052646307,47.422072 1.0380664,48.413461 3.1446965,48.413461 C 4.3321851,48.413461 29.360035,48.5596 32.051034,48.5596 C 34.165161,48.5596 34,46.5 34,46.5 C 34,43.834589 27.597902,41.598052 25.813453,39.641526 C 23.985035,37.640505 26,30.5 26,30.5 C 26.641306,28.9702 27,27.275084 27,25.5 C 27,18.600001 21.624002,13 15,13 z "
        id="path5176"
        sodipodi:nodetypes="cccccszcsc"
        transform="matrix(1,0,0,0.988192,0.447354,-1.486208)" />
     <path
-       sodipodi:type="arc"
-       style="opacity:1;fill:url(#radialGradient5286);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path5273"
-       sodipodi:cx="15.004828"
-       sodipodi:cy="39.80859"
-       sodipodi:rx="9.7225161"
-       sodipodi:ry="7.119638"
-       d="M 24.727345 39.80859 A 9.7225161 7.119638 0 1 1  5.2823124,39.80859 A 9.7225161 7.119638 0 1 1  24.727345 39.80859 z"
-       transform="matrix(0.977113,0,0,1.123653,-0.214066,-6.870732)" />
-    <path
-       style="opacity:0.5152838;fill:#5c3466;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M -42.833794,47.629347 C -42.833794,47.629347 -43.26687,44.687985 -40.223294,37.951005 C -40.223294,37.951005 -39.03087,40.509965 -38.631892,41.678764 C -39.153711,41.596001 -40.372039,41.685633 -40.372039,41.685633 C -40.038351,42.463101 -38.163796,45.952105 -36.121045,48.058218 C -37.780497,47.329365 -39.471111,47.196178 -39.471111,47.196178 C -39.009636,48.111847 -37.250115,48.69173 -36.943887,49.110993 C -36.943887,49.110993 -42.597127,49.864236 -42.833794,47.629347 z "
-       id="rect5312"
-       sodipodi:nodetypes="cccccccc"
-       transform="matrix(1.177457,0,0,1.083194,51.48278,-7.248017)" />
-    <path
-       style="opacity:0.5152838;fill:#5c3466;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M -49.441852,47.4154 C -48.364983,40.273995 -40.690447,44.765623 -40.961409,37.951005 C -40.961409,37.951005 -39.025024,40.280009 -38.974466,41.581367 C -39.496285,41.498604 -39.881988,41.516405 -39.881988,41.516405 C -39.5483,42.293873 -38.196948,45.748112 -36.154197,47.854225 C -37.813649,47.125372 -38.925816,46.898039 -38.925816,46.898039 C -38.847603,47.794771 -38.376224,47.369394 -38.122982,48.215235 C -42.942294,48.046898 -46.252916,49.195571 -49.441852,47.4154 z "
-       id="path5317"
-       sodipodi:nodetypes="cccccccc"
-       transform="matrix(-1.070093,0,0,1.114946,-18.74027,-7.453016)" />
-    <path
-       transform="matrix(1,0,0,0.988192,0.40625,-1.486208)"
-       style="opacity:0.31004367;fill:url(#linearGradient5310);fill-opacity:1;stroke:url(#linearGradient6512);stroke-width:1.00595677;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 15,14.0625 C 8.9877035,14.0625 4.0789961,19.13808 4.0625,25.46875 C 4.0624722,25.479427 4.0625,25.489316 4.0625,25.5 C 4.9744187,33.020507 4.3062656,37.469969 2.59375,40.59375 C -0.19778709,46.24536 1.5610206,47.490284 3.9033639,47.490284 C 5.8399452,47.490284 23.958121,47.46049 29.784094,47.46049 C 30.951301,47.46049 32.9375,47.964563 32.9375,46.5 C 32.9375,46.278257 32.737749,45.861323 32.1875,45.34375 C 31.637251,44.826177 30.81426,44.270409 29.90625,43.71875 C 28.99824,43.167091 28.02821,42.609033 27.15625,42.0625 C 26.28429,41.515967 25.511654,41.005793 24.96875,40.28125 C 24.358745,39.467156 24.078806,38.510169 24.024342,37.46875 C 23.969878,36.427331 24.107721,35.310041 24.224561,34.25 C 24.458241,32.129917 24.96875,30.28125 24.96875,30.28125 C 24.98374,30.216952 25.004663,30.154183 25.03125,30.09375 C 25.618731,28.692346 25.9375,27.131297 25.9375,25.5 C 25.9375,19.154404 21.022436,14.0625 15,14.0625 z "
+       style="opacity:0.5;fill:url(#radialGradient2824);fill-opacity:1;stroke:url(#linearGradient6512);stroke-width:0.99999994;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 15.5625,12.5 C 9.550204,12.5 4.641496,17.515648 4.625,23.771565 C 4.624972,23.782116 4.625,23.791888 4.625,23.802446 C 5.536919,31.234151 4.868766,35.631074 3.15625,38.717969 C 0.36471303,44.302845 2.123521,45.533069 4.465864,45.533069 C 6.402445,45.533069 24.520621,45.503627 30.346594,45.503627 C 31.513801,45.503627 33.5,46.001748 33.5,44.554478 C 33.5,44.335354 33.300249,43.923343 32.75,43.411881 C 32.199751,42.90042 31.37676,42.351214 30.46875,41.806069 C 29.56074,41.260924 28.59071,40.709456 27.71875,40.169376 C 26.84679,39.629297 26.074154,39.125147 25.53125,38.409159 C 24.921245,37.604678 24.641306,36.658991 24.586842,35.629869 C 24.532378,34.600747 24.670221,33.49665 24.787061,32.449126 C 25.020741,30.354077 25.53125,28.527239 25.53125,28.527239 C 25.54624,28.4637 25.567163,28.401673 25.59375,28.341953 C 26.181231,26.957097 26.5,25.414481 26.5,23.802446 C 26.5,17.531779 21.584936,12.5 15.5625,12.5 z "
        id="path5241"
        sodipodi:nodetypes="csscccssssssscssc" />
     <path
-       transform="matrix(-1.162197,-1.219912,1.095788,-1.150206,-4.404363,64.58016)"
        style="opacity:1;fill:#a46bb0;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 13.257119,24.626053 C 13.257119,26.227351 11.8279,27.316574 10.863875,27.316574 C 9.5428049,27.316574 8.4706318,26.01697 8.4706318,24.415672 C 8.4706318,23.024119 9.2055946,21.514771 10.526665,21.514771 C 11.847736,21.514771 13.257119,23.360971 13.257119,24.626053 z "
+       d="M 7.269301,19.503118 C 9.2717505,17.238166 12.529418,17.841584 13.808008,19.287784 C 15.560146,21.269611 15.356996,24.71627 13.354547,26.981222 C 11.614386,28.949501 8.7521391,29.981828 7,28 C 5.2478601,26.018172 5.6872953,21.292511 7.269301,19.503118 z "
        id="path5160"
        sodipodi:nodetypes="csssc" />
     <path
@@ -350,7 +383,7 @@
        sodipodi:rx="1.2410715"
        sodipodi:ry="1.2946428"
        d="M 11.410714 24.3125 A 1.2410715 1.2946428 0 1 1  8.928571,24.3125 A 1.2410715 1.2946428 0 1 1  11.410714 24.3125 z"
-       transform="matrix(1.208632,0,0,1.158617,-1.844007,-4.808565)" />
+       transform="matrix(1.208632,0,0,1.544828,-1.738701,-14.41893)" />
     <path
        sodipodi:type="arc"
        style="opacity:1;fill:black;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
@@ -360,11 +393,10 @@
        sodipodi:rx="1.2410715"
        sodipodi:ry="1.2946428"
        d="M 11.410714 24.3125 A 1.2410715 1.2946428 0 1 1  8.928571,24.3125 A 1.2410715 1.2946428 0 1 1  11.410714 24.3125 z"
-       transform="matrix(0.402878,0,0,0.386209,6.350228,13.9706)" />
+       transform="matrix(0.402878,0,0,0.514947,6.455534,10.62004)" />
     <path
-       transform="matrix(0.871648,-1.084366,-0.821841,-1.022405,36.71113,59.50016)"
        style="opacity:1;fill:#975fa3;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 13.257119,24.626053 C 13.257119,26.227351 11.8279,27.316574 10.863875,27.316574 C 9.5428049,27.316574 8.4706318,26.01697 8.4706318,24.415672 C 8.4706318,23.024119 9.2055946,21.514771 10.526665,21.514771 C 11.847736,21.514771 13.257119,23.360971 13.257119,24.626053 z "
+       d="M 27.88281,19.946791 C 26.359012,18.309616 23.880032,18.745786 22.907068,19.791141 C 21.573747,21.223665 21.728337,23.715015 23.252136,25.35219 C 24.576341,26.77492 26.754418,27.521117 28.087739,26.088593 C 29.42106,24.656068 29.086665,21.240217 27.88281,19.946791 z "
        id="path5167"
        sodipodi:nodetypes="csssc" />
     <path
@@ -382,7 +414,7 @@
        sodipodi:rx="1.2410715"
        sodipodi:ry="1.2946428"
        d="M 11.410714 24.3125 A 1.2410715 1.2946428 0 1 1  8.928571,24.3125 A 1.2410715 1.2946428 0 1 1  11.410714 24.3125 z"
-       transform="matrix(1.208632,0,0,1.158617,13.15599,-4.808572)" />
+       transform="matrix(1.208632,0,0,1.598777,13.20865,-15.80042)" />
     <path
        sodipodi:type="arc"
        style="opacity:1;fill:black;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
@@ -392,21 +424,19 @@
        sodipodi:rx="1.2410715"
        sodipodi:ry="1.2946428"
        d="M 11.410714 24.3125 A 1.2410715 1.2946428 0 1 1  8.928571,24.3125 A 1.2410715 1.2946428 0 1 1  11.410714 24.3125 z"
-       transform="matrix(0.402878,0,0,0.386209,21.35023,13.9706)" />
+       transform="matrix(0.402878,0,0,0.53293,21.40289,10.11299)" />
     <rect
        style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
        id="rect5215"
-       width="5.6071429"
-       height="2.1785715"
-       x="16"
-       y="27"
-       transform="matrix(1.070064,0,0,0.918028,-1.173674,3.073548)"
-       rx="1.0892857"
-       ry="1.0892857" />
+       width="7"
+       height="1.8602936"
+       x="15"
+       y="27.000017"
+       rx="0.81387848"
+       ry="0.93014681" />
     <path
-       transform="matrix(1.180326,0,0,0.867993,13.1795,-6.80859)"
-       style="fill:#f9751a;fill-opacity:1;stroke:none;stroke-width:1.0283047;stroke-miterlimit:4;stroke-opacity:1"
-       d="M -0.99929609,42.004237 C 3.5188333,45.348102 4.1278823,38.950282 4.9828709,38.950282 C 5.8260957,38.950282 6.1724645,45.375511 10.014606,42.007796 C 9.2074596,43.955072 6.7265914,47.014858 5.6807127,47.014858 C 4.6230593,47.014858 0.31231911,44.880662 -0.99929609,42.004237 z "
+       style="fill:#fcaf3e;fill-opacity:1;stroke:none;stroke-width:1.0283047;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 12.000005,28.650812 C 17.33287,31.553263 18.051747,26 19.060912,26 C 20.056192,26 20.46502,31.577054 25,28.653901 C 24.047304,30.344123 21.119071,32.999996 19.884593,32.999996 C 18.636217,32.999996 13.548138,31.147528 12.000005,28.650812 z "
        id="rect5187"
        sodipodi:nodetypes="czczc" />
     <path
@@ -422,9 +452,8 @@
        id="rect5189"
        sodipodi:nodetypes="cccc" />
     <path
-       transform="matrix(1.180326,0,0,0.867993,13.1795,-6.80859)"
-       style="fill:url(#linearGradient6569);fill-opacity:1.0;stroke:none;stroke-width:1.0283047;stroke-miterlimit:4;stroke-opacity:1"
-       d="M -0.99929609,42.004237 C 3.5188333,45.348102 4.1278823,38.950282 4.9828709,38.950282 C 5.8260957,38.950282 6.1724645,45.375511 10.014606,42.007796 C 9.2074596,43.955072 6.7265914,47.014858 5.6807127,47.014858 C 4.6230593,47.014858 0.31231911,44.880662 -0.99929609,42.004237 z "
+       style="fill:url(#linearGradient2856);fill-opacity:1;stroke:none;stroke-width:1.0283047;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 12.000005,28.650834 C 17.332871,31.553285 18.051747,26.000022 19.060912,26.000022 C 20.056192,26.000022 20.46502,31.577076 25,28.653923 C 24.047304,30.344145 21.119071,33.000018 19.884593,33.000018 C 18.636217,33.000018 13.548139,31.14755 12.000005,28.650834 z "
        id="path6561"
        sodipodi:nodetypes="czczc" />
   </g>
Binary file pidgin/pixmaps/status/16/available.png has changed
Binary file pidgin/pixmaps/status/16/away.png has changed
Binary file pidgin/pixmaps/status/16/busy.png has changed
Binary file pidgin/pixmaps/status/16/invisible.png has changed
Binary file pidgin/pixmaps/status/16/offline.png has changed
--- a/pidgin/pixmaps/status/16/scalable/available.svg	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/status/16/scalable/available.svg	Mon Jun 18 01:48:35 2007 +0000
@@ -7,23 +7,53 @@
    xmlns:svg="http://www.w3.org/2000/svg"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/s odipodi-0.dtd"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    width="16"
    height="16"
    id="svg2"
    sodipodi:version="0.32"
-   inkscape:version="0.43"
+   inkscape:version="0.44.1"
    version="1.0"
-   inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/status/16/available16.png"
+   inkscape:export-filename="/home/hbons/GUI/Tango/Gaim Refresh/status/16/available.png"
    inkscape:export-xdpi="90"
    inkscape:export-ydpi="90"
-   sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/status/16/scalable"
-   sodipodi:docname="available16.svg">
+   sodipodi:docbase="/home/hbons/Desktop/experiment/status/16/scalable"
+   sodipodi:docname="available.svg">
   <defs
      id="defs4">
     <linearGradient
        inkscape:collect="always"
+       id="linearGradient2898">
+      <stop
+         style="stop-color:white;stop-opacity:1;"
+         offset="0"
+         id="stop2900" />
+      <stop
+         style="stop-color:white;stop-opacity:0;"
+         offset="1"
+         id="stop2902" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient4738"
+       gradientUnits="userSpaceOnUse"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient4740"
+       gradientUnits="userSpaceOnUse"
+       x1="15.498499"
+       y1="9.4211226"
+       x2="24.240097"
+       y2="36.603138" />
+    <linearGradient
+       inkscape:collect="always"
        xlink:href="#linearGradient3149"
        id="linearGradient2269"
        gradientUnits="userSpaceOnUse"
@@ -86,6 +116,118 @@
        x2="12.233074"
        y2="27.77807"
        gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2898"
+       id="radialGradient2904"
+       cx="4.8470273"
+       cy="6.9473476"
+       fx="4.8470273"
+       fy="6.9473476"
+       r="0.8078171"
+       gradientTransform="matrix(3.018423,0.664359,-1.388844,4.257661,-0.134567,-26.02469)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient2818"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="11.024895"
+       x2="10.623409"
+       y1="2.7991772"
+       x1="4.5264969"
+       id="linearGradient2810"
+       xlink:href="#linearGradient2804"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       id="linearGradient2963"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2951">
+      <stop
+         id="stop2953"
+         offset="0"
+         style="stop-color:#73d216;stop-opacity:1;" />
+      <stop
+         id="stop2955"
+         offset="1"
+         style="stop-color:#5ca911;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       y2="40.032413"
+       x2="17.890068"
+       y1="8.0617304"
+       x1="17.890068"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2949"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2804"
+       inkscape:collect="always">
+      <stop
+         id="stop2806"
+         offset="0"
+         style="stop-color:white;stop-opacity:1;" />
+      <stop
+         id="stop2808"
+         offset="1"
+         style="stop-color:white;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2812"
+       inkscape:collect="always">
+      <stop
+         id="stop2814"
+         offset="0"
+         style="stop-color:#2e3436;stop-opacity:1;" />
+      <stop
+         id="stop2816"
+         offset="1"
+         style="stop-color:#2e3436;stop-opacity:0;" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient3005"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2804"
+       id="linearGradient3007"
+       gradientUnits="userSpaceOnUse"
+       x1="4.5264969"
+       y1="2.7991772"
+       x2="10.623409"
+       y2="11.024895" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient3025"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
   </defs>
   <sodipodi:namedview
      id="base"
@@ -95,16 +237,16 @@
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
      inkscape:zoom="25.992076"
-     inkscape:cx="16.806787"
-     inkscape:cy="8.1662141"
+     inkscape:cx="4.1907826"
+     inkscape:cy="8.6773979"
      inkscape:document-units="px"
      inkscape:current-layer="layer1"
      showgrid="true"
      fill="#eeeeec"
-     inkscape:window-width="1268"
-     inkscape:window-height="968"
-     inkscape:window-x="6"
-     inkscape:window-y="21" />
+     inkscape:window-width="1274"
+     inkscape:window-height="844"
+     inkscape:window-x="3"
+     inkscape:window-y="0" />
   <metadata
      id="metadata7">
     <rdf:RDF>
@@ -126,37 +268,19 @@
        sodipodi:rx="8.6620579"
        sodipodi:cy="19.008621"
        sodipodi:cx="31.112698"
-       id="path4318"
-       style="opacity:0.7;color:#000000;fill:url(#radialGradient3822);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       sodipodi:type="arc"
-       transform="matrix(0.923568,0,0,0.288615,-20.73469,8.013827)" />
-    <path
+       id="path2969"
+       style="color:black;fill:url(#radialGradient3025);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
        sodipodi:type="arc"
-       style="opacity:1;fill:url(#linearGradient2857);fill-opacity:1;fill-rule:evenodd;stroke:#418203;stroke-width:1.85686159;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path2245"
-       sodipodi:cx="17.890068"
-       sodipodi:cy="17.572527"
-       sodipodi:rx="13.932817"
-       sodipodi:ry="13.932817"
-       d="M 31.822886 17.572527 A 13.932817 13.932817 0 1 1  3.9572506,17.572527 A 13.932817 13.932817 0 1 1  31.822886 17.572527 z"
-       transform="matrix(0.538543,0,0,0.538542,-1.633369,-1.462358)" />
-    <image
-       id="image1323"
-       height="64.794617"
-       width="64.794617"
-       sodipodi:absref="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-       xlink:href="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-       x="-74"
-       y="-17" />
+       transform="matrix(0.923568,0,0,0.173169,-20.73469,11.2083)" />
     <path
-       sodipodi:type="arc"
-       style="opacity:0.5;fill:url(#linearGradient2269);fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.14505577;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path3145"
-       sodipodi:cx="17.890068"
-       sodipodi:cy="17.572527"
-       sodipodi:rx="13.932817"
-       sodipodi:ry="13.932817"
-       d="M 31.822886 17.572527 A 13.932817 13.932817 0 1 1  3.9572506,17.572527 A 13.932817 13.932817 0 1 1  31.822886 17.572527 z"
-       transform="matrix(0.466166,0,0,0.466212,-0.33531,-0.188412)" />
+       transform="matrix(0.538297,0,0,0.538297,-1.630177,-1.459246)"
+       style="fill:url(#linearGradient4738);fill-opacity:1;fill-rule:evenodd;stroke:#306300;stroke-width:1.85770929;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 31.822886,17.572527 C 31.822886,25.263442 25.580983,31.505344 17.890068,31.505344 C 10.199153,31.505344 3.9572506,25.263442 3.9572506,17.572527 C 3.9572506,9.8816117 10.199153,3.6397095 17.890068,3.6397095 C 25.580983,3.6397095 31.822886,9.8816117 31.822886,17.572527 z "
+       id="path4331" />
+    <path
+       transform="matrix(0.466524,0,0,0.466525,-0.346154,-0.198015)"
+       style="opacity:0.6;fill:url(#linearGradient4740);fill-opacity:1;fill-rule:evenodd;stroke:white;stroke-width:2.14350748;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 31.822886,17.572527 C 31.822886,25.263442 25.580983,31.505344 17.890068,31.505344 C 10.199153,31.505344 3.9572506,25.263442 3.9572506,17.572527 C 3.9572506,9.8816117 10.199153,3.6397095 17.890068,3.6397095 C 25.580983,3.6397095 31.822886,9.8816117 31.822886,17.572527 z "
+       id="path4333" />
   </g>
 </svg>
--- a/pidgin/pixmaps/status/16/scalable/away.svg	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/status/16/scalable/away.svg	Mon Jun 18 01:48:35 2007 +0000
@@ -7,43 +7,45 @@
    xmlns:svg="http://www.w3.org/2000/svg"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/s odipodi-0.dtd"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    width="16"
    height="16"
    id="svg2"
    sodipodi:version="0.32"
-   inkscape:version="0.43"
+   inkscape:version="0.44.1"
    version="1.0"
    inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/status/16/available16.png"
    inkscape:export-xdpi="90"
    inkscape:export-ydpi="90"
-   sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/status/16/scalable"
-   sodipodi:docname="away16.svg">
+   sodipodi:docbase="/home/hbons/Desktop/experiment/status/16/scalable"
+   sodipodi:docname="away.svg">
   <defs
      id="defs4">
     <linearGradient
        inkscape:collect="always"
-       id="linearGradient2239">
+       id="linearGradient2812">
       <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
+         style="stop-color:#2e3436;stop-opacity:1;"
          offset="0"
-         id="stop2241" />
+         id="stop2814" />
       <stop
-         style="stop-color:#ffffff;stop-opacity:0;"
+         style="stop-color:#2e3436;stop-opacity:0;"
          offset="1"
-         id="stop2243" />
+         id="stop2816" />
     </linearGradient>
     <linearGradient
        inkscape:collect="always"
-       xlink:href="#linearGradient2239"
-       id="linearGradient2245"
-       x1="15.602553"
-       y1="1.5657365"
-       x2="15.522223"
-       y2="33.483475"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.482882,0,0,0.482874,0.269812,0.26982)" />
+       id="linearGradient2804">
+      <stop
+         style="stop-color:white;stop-opacity:1;"
+         offset="0"
+         id="stop2806" />
+      <stop
+         style="stop-color:white;stop-opacity:0;"
+         offset="1"
+         id="stop2808" />
+    </linearGradient>
     <linearGradient
        inkscape:collect="always"
        xlink:href="#linearGradient3149"
@@ -78,29 +80,6 @@
     </linearGradient>
     <linearGradient
        inkscape:collect="always"
-       id="linearGradient3816">
-      <stop
-         style="stop-color:#000000;stop-opacity:1;"
-         offset="0"
-         id="stop3818" />
-      <stop
-         style="stop-color:#000000;stop-opacity:0;"
-         offset="1"
-         id="stop3820" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3816"
-       id="radialGradient3822"
-       cx="31.112698"
-       cy="19.008621"
-       fx="31.112698"
-       fy="19.008621"
-       r="8.6620579"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.914124,-3.896132e-15,-2.475021e-18,1.631747,2.671799,-12.00863)" />
-    <linearGradient
-       inkscape:collect="always"
        xlink:href="#linearGradient2851"
        id="linearGradient2857"
        x1="6.878005"
@@ -108,6 +87,25 @@
        x2="12.233074"
        y2="27.77807"
        gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2804"
+       id="linearGradient2810"
+       x1="4.5264969"
+       y1="2.7991772"
+       x2="10.623409"
+       y2="11.024895"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient2818"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
   </defs>
   <sodipodi:namedview
      id="base"
@@ -117,16 +115,20 @@
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
      inkscape:zoom="25.992076"
-     inkscape:cx="16.806787"
-     inkscape:cy="8.1662141"
+     inkscape:cx="14.729231"
+     inkscape:cy="2.7799575"
      inkscape:document-units="px"
      inkscape:current-layer="layer1"
      showgrid="true"
      fill="#eeeeec"
-     inkscape:window-width="1268"
-     inkscape:window-height="968"
-     inkscape:window-x="6"
-     inkscape:window-y="21" />
+     inkscape:window-width="1434"
+     inkscape:window-height="844"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:object-paths="false"
+     inkscape:grid-bbox="true"
+     inkscape:guide-bbox="false"
+     inkscape:grid-points="true" />
   <metadata
      id="metadata7">
     <rdf:RDF>
@@ -149,20 +151,12 @@
        sodipodi:cy="19.008621"
        sodipodi:cx="31.112698"
        id="path4318"
-       style="opacity:0.7;color:#000000;fill:url(#radialGradient3822);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       style="opacity:1;color:black;fill:url(#radialGradient2818);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
        sodipodi:type="arc"
-       transform="matrix(0.923568,0,0,0.288615,-20.73469,8.013827)" />
-    <image
-       id="image1323"
-       height="64.794617"
-       width="64.794617"
-       sodipodi:absref="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-       xlink:href="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-       x="-74"
-       y="-17" />
+       transform="matrix(0.923568,0,0,0.173169,-20.73469,11.2083)" />
     <path
        sodipodi:type="arc"
-       style="opacity:1;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:evenodd;stroke:#204a87;stroke-width:1.91314828px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       style="opacity:1;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:evenodd;stroke:#173867;stroke-width:1.91314828px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
        id="path1339"
        sodipodi:cx="15.590227"
        sodipodi:cy="16.57217"
@@ -172,47 +166,113 @@
        transform="matrix(0.522697,0,0,0.522697,-0.148088,-0.661348)" />
     <path
        sodipodi:type="arc"
-       style="opacity:1;color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#204a87;stroke-width:2.59300995px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       style="opacity:1;fill:#8ab0d7;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="path2788"
+       sodipodi:cx="-3.8088531"
+       sodipodi:cy="3.303823"
+       sodipodi:rx="3.1932809"
+       sodipodi:ry="3.3471739"
+       d="M -0.61557221 3.303823 A 3.1932809 3.3471739 0 1 1  -7.0021341,3.303823 A 3.1932809 3.3471739 0 1 1  -0.61557221 3.303823 z"
+       transform="matrix(2.192102,0,0,2.091316,16.34939,1.090661)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:0.40340911;color:black;fill:#babdb6;fill-opacity:1;fill-rule:evenodd;stroke:#173867;stroke-width:2.60821199px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
        id="path1341"
        sodipodi:cx="15.590227"
        sodipodi:cy="16.57217"
        sodipodi:rx="14.345175"
        sodipodi:ry="14.345175"
        d="M 29.935402 16.57217 A 14.345175 14.345175 0 1 1  1.2450523,16.57217 A 14.345175 14.345175 0 1 1  29.935402 16.57217 z"
-       transform="matrix(0.385634,0,0,0.38567,1.998372,1.598697)" />
+       transform="matrix(0.383404,0,0,0.383404,2.022641,1.646167)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:1;fill:#dcdcd8;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="path2796"
+       sodipodi:cx="6.0403023"
+       sodipodi:cy="7.5551186"
+       sodipodi:rx="1.615877"
+       sodipodi:ry="1.3273276"
+       d="M 7.6561793 7.5551186 A 1.615877 1.3273276 0 1 1  4.4244252,7.5551186 A 1.615877 1.3273276 0 1 1  7.6561793 7.5551186 z"
+       transform="matrix(3.094296,0,0,3.766968,-10.69048,-20.45989)" />
     <path
        sodipodi:type="arc"
-       style="opacity:1;color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#2e3436;stroke-width:9.63841057px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       id="path2216"
-       sodipodi:cx="15.590227"
-       sodipodi:cy="16.57217"
-       sodipodi:rx="14.345175"
-       sodipodi:ry="14.345175"
-       d="M 29.935402 16.57217 A 14.345175 14.345175 0 1 1  1.2450523,16.57217 A 14.345175 14.345175 0 1 1  29.935402 16.57217 z"
-       transform="matrix(0.103753,0,0,0.103753,6.37887,6.27699)" />
-    <path
-       style="opacity:0.5;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient2245);stroke-width:0.99999881px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       d="M 14.509853,7.9958041 C 14.509853,11.591436 11.591612,14.50963 7.9959211,14.50963 C 4.4002314,14.50963 1.4819904,11.591436 1.4819904,7.9958041 C 1.4819904,4.4001725 4.4002314,1.4819783 7.9959211,1.4819783 C 11.591612,1.4819783 14.509853,4.4001725 14.509853,7.9958041 z "
-       id="path2220" />
+       style="opacity:0.76704544;fill:none;fill-opacity:1;stroke:url(#linearGradient2810);stroke-width:0.80677563;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="path2802"
+       sodipodi:cx="7.5"
+       sodipodi:cy="7"
+       sodipodi:rx="5.5"
+       sodipodi:ry="5"
+       d="M 13 7 A 5.5 5 0 1 1  2,7 A 5.5 5 0 1 1  13 7 z"
+       transform="matrix(1.18182,0,0,1.3,-0.86365,-1.1)" />
+    <rect
+       style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2820"
+       width="1"
+       height="1"
+       x="5"
+       y="-11"
+       transform="matrix(0,1,-1,0,0,0)" />
+    <rect
+       style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2832"
+       width="1"
+       height="1"
+       x="7"
+       y="-9"
+       transform="matrix(0,1,-1,0,0,0)" />
     <path
        sodipodi:type="arc"
+       style="opacity:1;fill:white;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="path2852"
+       sodipodi:cx="6.0403023"
+       sodipodi:cy="7.5551186"
+       sodipodi:rx="1.615877"
+       sodipodi:ry="1.3273276"
+       d="M 4.835244,8.4394021 A 1.615877,1.3273276 0 0 1 6.0776839,6.2281462 L 6.0403023,7.5551186 z"
+       transform="matrix(2.475436,0,0,3.013575,-6.952382,-14.76791)"
+       sodipodi:start="2.4124729"
+       sodipodi:end="4.735525" />
+    <rect
        style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path1588"
-       sodipodi:cx="20.264311"
-       sodipodi:cy="14.476474"
-       sodipodi:rx="2.9448855"
-       sodipodi:ry="0.78724658"
-       d="M 23.209196 14.476474 A 2.9448855 0.78724658 0 1 1  17.319425,14.476474 A 2.9448855 0.78724658 0 1 1  23.209196 14.476474 z"
-       transform="matrix(-1.244057e-16,-0.509358,1.270255,5.747542e-7,-10.38882,15.82177)" />
-    <path
-       sodipodi:type="arc"
+       id="rect2838"
+       width="2"
+       height="2"
+       x="7"
+       y="-9"
+       rx="1"
+       ry="1"
+       transform="matrix(0,1,-1,0,0,0)" />
+    <rect
+       style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2840"
+       width="1"
+       height="1"
+       x="6"
+       y="-10"
+       transform="matrix(0,1,-1,0,0,0)" />
+    <rect
        style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path1314"
-       sodipodi:cx="20.264311"
-       sodipodi:cy="14.476474"
-       sodipodi:rx="2.9448855"
-       sodipodi:ry="0.78724658"
-       d="M 23.209196 14.476474 A 2.9448855 0.78724658 0 1 1  17.319425,14.476474 A 2.9448855 0.78724658 0 1 1  23.209196 14.476474 z"
-       transform="matrix(0.509355,-4.991037e-16,-5.747516e-7,1.270255,0.178284,-10.38882)" />
+       id="rect2846"
+       width="1"
+       height="1"
+       x="-11"
+       y="-11"
+       transform="matrix(0,-1,-1,0,0,0)" />
+    <rect
+       style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2848"
+       width="1"
+       height="1"
+       x="-9"
+       y="-9"
+       transform="matrix(0,-1,-1,0,0,0)" />
+    <rect
+       style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2850"
+       width="1"
+       height="1"
+       x="-10"
+       y="-10"
+       transform="matrix(0,-1,-1,0,0,0)" />
   </g>
 </svg>
--- a/pidgin/pixmaps/status/16/scalable/busy.svg	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/status/16/scalable/busy.svg	Mon Jun 18 01:48:35 2007 +0000
@@ -7,23 +7,68 @@
    xmlns:svg="http://www.w3.org/2000/svg"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/s odipodi-0.dtd"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    width="16"
    height="16"
    id="svg2"
    sodipodi:version="0.32"
-   inkscape:version="0.43"
+   inkscape:version="0.44.1"
    version="1.0"
    inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/status/16/available16.png"
    inkscape:export-xdpi="90"
    inkscape:export-ydpi="90"
-   sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/status/16/scalable"
-   sodipodi:docname="busy16.svg">
+   sodipodi:docbase="/home/hbons/Desktop/experiment/status/16/scalable"
+   sodipodi:docname="busy.svg">
   <defs
      id="defs4">
     <linearGradient
        inkscape:collect="always"
+       id="linearGradient2898">
+      <stop
+         style="stop-color:white;stop-opacity:1;"
+         offset="0"
+         id="stop2900" />
+      <stop
+         style="stop-color:white;stop-opacity:0;"
+         offset="1"
+         id="stop2902" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2898"
+       id="radialGradient2904"
+       cx="4.8470273"
+       cy="6.9473476"
+       fx="4.8470273"
+       fy="6.9473476"
+       r="0.8078171"
+       gradientTransform="matrix(3.018423,0.664359,-1.388844,4.257661,-0.134567,-26.02469)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient2812"
+       inkscape:collect="always">
+      <stop
+         id="stop2814"
+         offset="0"
+         style="stop-color:#2e3436;stop-opacity:1;" />
+      <stop
+         id="stop2816"
+         offset="1"
+         style="stop-color:#2e3436;stop-opacity:0;" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient3025"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       inkscape:collect="always"
        id="linearGradient2186">
       <stop
          style="stop-color:#ffffff;stop-opacity:1;"
@@ -38,8 +83,8 @@
        inkscape:collect="always"
        xlink:href="#linearGradient2186"
        id="linearGradient2194"
-       x1="11.226587"
-       y1="-5.4832759"
+       x1="9.2594385"
+       y1="-1.5641226"
        x2="11.226587"
        y2="17.697369"
        gradientUnits="userSpaceOnUse"
@@ -60,10 +105,10 @@
        inkscape:collect="always"
        xlink:href="#linearGradient2239"
        id="linearGradient2245"
-       x1="15.602553"
-       y1="1.5657365"
-       x2="15.522223"
-       y2="33.483475"
+       x1="8.7505674"
+       y1="4.5934086"
+       x2="31.18539"
+       y2="39.834526"
        gradientUnits="userSpaceOnUse"
        gradientTransform="matrix(0.482882,0,0,0.482874,0.269812,0.26982)" />
     <linearGradient
@@ -139,16 +184,16 @@
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
      inkscape:zoom="25.992076"
-     inkscape:cx="16.806787"
-     inkscape:cy="8.1662141"
+     inkscape:cx="8.3811422"
+     inkscape:cy="5.1075896"
      inkscape:document-units="px"
      inkscape:current-layer="layer1"
      showgrid="true"
      fill="#eeeeec"
      inkscape:window-width="1268"
-     inkscape:window-height="968"
+     inkscape:window-height="844"
      inkscape:window-x="6"
-     inkscape:window-y="21" />
+     inkscape:window-y="0" />
   <metadata
      id="metadata7">
     <rdf:RDF>
@@ -170,18 +215,10 @@
        sodipodi:rx="8.6620579"
        sodipodi:cy="19.008621"
        sodipodi:cx="31.112698"
-       id="path4318"
-       style="opacity:0.7;color:#000000;fill:url(#radialGradient3822);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       id="path2969"
+       style="color:black;fill:url(#radialGradient3025);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
        sodipodi:type="arc"
-       transform="matrix(0.923568,0,0,0.288615,-20.73469,8.013827)" />
-    <image
-       id="image1323"
-       height="64.794617"
-       width="64.794617"
-       sodipodi:absref="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-       xlink:href="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-       x="-74"
-       y="-17" />
+       transform="matrix(0.923568,0,0,0.173169,-20.73469,11.2083)" />
     <path
        sodipodi:type="arc"
        style="opacity:1;color:#000000;fill:#ef2929;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.36561811px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
@@ -194,7 +231,7 @@
        transform="matrix(0.468971,0,0,0.468971,0.730372,0.26987)" />
     <path
        sodipodi:type="arc"
-       style="opacity:1;color:#000000;fill:#ef2929;fill-opacity:1;fill-rule:evenodd;stroke:#a40000;stroke-width:1.91298747px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       style="opacity:1;color:#000000;fill:#f24747;fill-opacity:1;fill-rule:evenodd;stroke:#820000;stroke-width:1.91298747px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
        id="path1339"
        sodipodi:cx="15.590227"
        sodipodi:cy="16.57217"
@@ -206,10 +243,14 @@
        style="opacity:0.6;color:#000000;fill:url(#linearGradient2194);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient2245);stroke-width:1.00000012px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
        d="M 14.525974,7.9894993 C 14.525974,11.598577 11.608166,14.527685 8.0130095,14.527685 C 4.4178543,14.527685 1.500047,11.598577 1.500047,7.9894993 C 1.500047,4.3804219 4.4178543,1.4513155 8.0130095,1.4513155 C 11.608166,1.4513155 14.525974,4.3804219 14.525974,7.9894993 z "
        id="path2220" />
-    <path
-       style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#a40000;stroke-width:0.99999833px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       d="M 13.49379,7.9436678 C 13.49379,9.8082522 12.846021,9.4786261 7.9525684,9.4786261 C 3.1055026,9.4786261 2.5041877,9.7778545 2.5041877,8.0257093 C 2.5041877,6.2462172 3.8951545,6.5604085 7.9989886,6.5604085 C 12.072197,6.5604085 13.49379,6.0517387 13.49379,7.9436678 z "
-       id="path1341"
-       sodipodi:nodetypes="czzzz" />
+    <rect
+       style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:#a40000;stroke-width:1.00000024;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect3207"
+       width="11.000004"
+       height="2.9999959"
+       x="2.500001"
+       y="6.5000038"
+       rx="0.96183157"
+       ry="0.96183157" />
   </g>
 </svg>
--- a/pidgin/pixmaps/status/16/scalable/offline.svg	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/status/16/scalable/offline.svg	Mon Jun 18 01:48:35 2007 +0000
@@ -15,10 +15,10 @@
    sodipodi:version="0.32"
    inkscape:version="0.44.1"
    version="1.0"
-   inkscape:export-filename="/home/hbons/GUI/Tango/Gaim Refresh/status/16/offline.png"
+   inkscape:export-filename="/home/hbons/Desktop/offline.png"
    inkscape:export-xdpi="90"
    inkscape:export-ydpi="90"
-   sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/status/16/scalable"
+   sodipodi:docbase="/home/hbons/Desktop/experiment/status/16/scalable"
    sodipodi:docname="offline.svg">
   <defs
      id="defs4">
@@ -160,16 +160,16 @@
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
      inkscape:zoom="25.992076"
-     inkscape:cx="16.806787"
-     inkscape:cy="8.1469775"
+     inkscape:cx="26.27121"
+     inkscape:cy="5.5692688"
      inkscape:document-units="px"
      inkscape:current-layer="layer1"
      showgrid="true"
      fill="#eeeeec"
-     inkscape:window-width="1268"
-     inkscape:window-height="968"
-     inkscape:window-x="6"
-     inkscape:window-y="23" />
+     inkscape:window-width="1434"
+     inkscape:window-height="844"
+     inkscape:window-x="0"
+     inkscape:window-y="0" />
   <metadata
      id="metadata7">
     <rdf:RDF>
@@ -195,14 +195,6 @@
        style="opacity:0.7;color:#000000;fill:url(#radialGradient3822);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
        sodipodi:type="arc"
        transform="matrix(0.923568,0,0,0.288615,-20.73469,8.013827)" />
-    <image
-       id="image1323"
-       height="64.794617"
-       width="64.794617"
-       sodipodi:absref="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-       xlink:href="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-       x="-74"
-       y="-17" />
     <path
        style="fill:#888a85;fill-opacity:1;stroke:#2e3436;stroke-width:0.99999827;stroke-miterlimit:4;stroke-opacity:1"
        d="M 13.307074,13.307079 C 10.376958,16.237198 5.6213214,16.237693 2.6918157,13.308187 C -0.23769028,10.378679 -0.23719421,5.623042 2.692923,2.6929237 C 5.62304,-0.23719442 10.378675,-0.23769056 13.308181,2.6918165 C 16.237687,5.6213234 16.237192,10.376962 13.307074,13.307079 z "
@@ -218,9 +210,9 @@
        d="M 8,1.5 C 6.3326173,1.5001739 4.674966,2.1375335 3.40625,3.40625 C 0.86479124,5.9477097 0.86538373,10.052882 3.40625,12.59375 C 5.9471154,15.134616 10.052293,15.135209 12.59375,12.59375 C 15.135209,10.052292 15.134616,5.9471167 12.59375,3.40625 C 11.325315,2.1378146 9.6669929,1.4998261 8,1.5 z "
        transform="matrix(1.000056,0,0,1.000028,-4.353349e-4,-2.926381e-5)" />
     <path
-       style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:#555753;stroke-width:0.99999946;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 10.018233,3.7131793 L 8,5.8786797 L 5.9817663,3.727906 L 3.7131793,5.9817663 L 5.8786797,8 L 3.7131793,10.03296 L 5.9964929,12.316274 L 8,10.12132 L 10.018233,12.301548 L 12.301548,10.018233 L 10.12132,8 L 12.286821,5.9964929 L 10.018233,3.7131793 z "
-       id="rect1322"
-       sodipodi:nodetypes="ccccccccccccc" />
+       style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:#555753;stroke-width:1.00000036;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 11.54182,4.2658182 C 10.931116,3.6551131 10.447965,3.347327 9.8372602,3.9580321 L 8.0000001,5.7952921 L 6.1627401,3.9580321 C 5.5520351,3.3473271 4.9919392,3.7705329 4.381234,4.381238 C 3.770529,4.991943 3.347323,5.5520393 3.9580281,6.1627441 L 5.7952881,8.0000041 L 3.9580281,9.8372641 C 3.3473229,10.447969 3.6935827,10.969592 4.3042875,11.580298 C 4.9149927,12.191002 5.5520349,12.652681 6.1627401,12.041977 L 8.0000001,10.204716 L 9.8372602,12.041977 C 10.447965,12.652681 11.046535,12.306422 11.657239,11.695718 C 12.267944,11.085012 12.652677,10.447969 12.041972,9.8372641 L 10.204713,8.0000041 L 12.041972,6.1627441 C 12.652677,5.552039 12.152526,4.8765236 11.54182,4.2658182 z "
+       id="rect2920"
+       sodipodi:nodetypes="ccccscccscccscccc" />
   </g>
 </svg>
Binary file pidgin/pixmaps/status/22/available.png has changed
Binary file pidgin/pixmaps/status/22/away.png has changed
Binary file pidgin/pixmaps/status/22/invisible.png has changed
Binary file pidgin/pixmaps/status/22/offline.png has changed
--- a/pidgin/pixmaps/status/22/scalable/available.svg	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/status/22/scalable/available.svg	Mon Jun 18 01:48:35 2007 +0000
@@ -7,19 +7,19 @@
    xmlns:svg="http://www.w3.org/2000/svg"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/s odipodi-0.dtd"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    width="24"
    height="24"
    id="svg2"
    sodipodi:version="0.32"
-   inkscape:version="0.43"
+   inkscape:version="0.44.1"
    version="1.0"
-   inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/status/22/available22.png"
+   inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/status/32/available32.png"
    inkscape:export-xdpi="90"
    inkscape:export-ydpi="90"
-   sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/status/22"
-   sodipodi:docname="available22.svg">
+   sodipodi:docbase="/home/hbons/Desktop/experiment/22/scalable"
+   sodipodi:docname="available.svg">
   <defs
      id="defs4">
     <linearGradient
@@ -72,14 +72,316 @@
        xlink:href="#linearGradient3149"
        id="linearGradient3155"
        x1="17.890068"
-       y1="2.197206"
+       y1="8.3091545"
        x2="17.890068"
-       y2="18.507565"
+       y2="36.574547"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient3025"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="11.024895"
+       x2="10.623409"
+       y1="2.7991772"
+       x1="4.5264969"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3007"
+       xlink:href="#linearGradient2804"
+       inkscape:collect="always" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient3005"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2812">
+      <stop
+         style="stop-color:#2e3436;stop-opacity:1;"
+         offset="0"
+         id="stop2814" />
+      <stop
+         style="stop-color:#2e3436;stop-opacity:0;"
+         offset="1"
+         id="stop2816" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2804">
+      <stop
+         style="stop-color:white;stop-opacity:1;"
+         offset="0"
+         id="stop2806" />
+      <stop
+         style="stop-color:white;stop-opacity:0;"
+         offset="1"
+         id="stop2808" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2949"
+       gradientUnits="userSpaceOnUse"
+       x1="17.890068"
+       y1="8.0617304"
+       x2="17.890068"
+       y2="40.032413" />
+    <linearGradient
+       id="linearGradient2951">
+      <stop
+         style="stop-color:#73d216;stop-opacity:1;"
+         offset="0"
+         id="stop2953" />
+      <stop
+         style="stop-color:#5ca911;stop-opacity:1;"
+         offset="1"
+         id="stop2955" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient2963"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807"
        gradientUnits="userSpaceOnUse" />
     <linearGradient
        inkscape:collect="always"
+       xlink:href="#linearGradient2804"
+       id="linearGradient2810"
+       x1="4.5264969"
+       y1="2.7991772"
+       x2="10.623409"
+       y2="11.024895"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient2818"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(3.018423,0.664359,-1.388844,4.257661,-0.134567,-26.02469)"
+       r="0.8078171"
+       fy="6.9473476"
+       fx="4.8470273"
+       cy="6.9473476"
+       cx="4.8470273"
+       id="radialGradient2904"
+       xlink:href="#linearGradient2898"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       id="linearGradient1955"
        xlink:href="#linearGradient2851"
-       id="linearGradient2857"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientTransform="matrix(0.914124,0,0,1.631747,2.671799,-12.00863)"
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient1953"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient1935">
+      <stop
+         id="stop1937"
+         offset="0"
+         style="stop-color:#73d216;stop-opacity:1;" />
+      <stop
+         id="stop1939"
+         offset="1"
+         style="stop-color:#5ca911;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       y2="40.032413"
+       x2="17.890068"
+       y1="8.0617304"
+       x1="17.890068"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2269"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="36.603138"
+       x2="24.240097"
+       y1="9.4211226"
+       x1="15.498499"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient4740"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient4738"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2898"
+       inkscape:collect="always">
+      <stop
+         id="stop2900"
+         offset="0"
+         style="stop-color:white;stop-opacity:1;" />
+      <stop
+         id="stop2902"
+         offset="1"
+         style="stop-color:white;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient1983"
+       gradientUnits="userSpaceOnUse"
+       x1="15.498499"
+       y1="9.4211226"
+       x2="24.240097"
+       y2="36.603138"
+       gradientTransform="matrix(1.004822,0,0,1.004822,-2.476351,-2.157242)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient1986"
+       gradientUnits="userSpaceOnUse"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807"
+       gradientTransform="matrix(1.076595,0,0,1.076595,-3.760351,-3.418494)" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2898"
+       id="radialGradient1990"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(3.018423,0.664359,-1.388844,4.257661,-0.134567,-26.02469)"
+       cx="4.8470273"
+       cy="6.9473476"
+       fx="4.8470273"
+       fy="6.9473476"
+       r="0.8078171" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient1992"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       y2="21.045444"
+       x2="15.602553"
+       y1="1.5657365"
+       x1="15.602553"
+       gradientTransform="matrix(0.705322,0,0,0.705327,8.71963,7.710084)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2073"
+       xlink:href="#linearGradient2239"
+       inkscape:collect="always" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2057"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3816"
+       id="radialGradient2032"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2239"
+       id="linearGradient2040"
+       x1="15.602553"
+       y1="1.5657365"
+       x2="15.522223"
+       y2="33.483475"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.999824,0,0,0.999281,2.209264e-4,5.644055e-4)" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1985"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="11.024895"
+       x2="10.623409"
+       y1="2.7991772"
+       x1="4.5264969"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2100"
+       xlink:href="#linearGradient2804"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2086"
+       gradientUnits="userSpaceOnUse"
+       x1="17.890068"
+       y1="8.0617304"
+       x2="17.890068"
+       y2="40.032413" />
+    <linearGradient
+       id="linearGradient2080">
+      <stop
+         style="stop-color:#73d216;stop-opacity:1;"
+         offset="0"
+         id="stop2082" />
+      <stop
+         style="stop-color:#5ca911;stop-opacity:1;"
+         offset="1"
+         id="stop2084" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient2072"
        x1="6.878005"
        y1="11.789385"
        x2="12.233074"
@@ -87,13 +389,386 @@
        gradientUnits="userSpaceOnUse" />
     <linearGradient
        inkscape:collect="always"
+       xlink:href="#linearGradient2804"
+       id="linearGradient2070"
+       x1="4.5264969"
+       y1="2.7991772"
+       x2="10.623409"
+       y2="11.024895"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient2068"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.493392,0,4.185903)"
+       r="5.7619157"
+       fy="5.3375292"
+       fx="10.99079"
+       cy="5.3375292"
+       cx="10.99079"
+       id="radialGradient5135"
+       xlink:href="#linearGradient5129"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2239"
+       inkscape:collect="always">
+      <stop
+         id="stop2241"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop2243"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+    </linearGradient>
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.842757,0,0,-0.35721,19.80716,14.19321)"
+       r="6.6449099"
+       fy="10.457643"
+       fx="10.748654"
+       cy="10.457643"
+       cx="10.748654"
+       id="radialGradient3156"
+       xlink:href="#linearGradient3150"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient3150"
+       inkscape:collect="always">
+      <stop
+         id="stop3152"
+         offset="0"
+         style="stop-color:#2e3436;stop-opacity:1;" />
+      <stop
+         id="stop3154"
+         offset="1"
+         style="stop-color:#2e3436;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient5129"
+       inkscape:collect="always">
+      <stop
+         id="stop5131"
+         offset="0"
+         style="stop-color:white;stop-opacity:1;" />
+      <stop
+         id="stop5133"
+         offset="1"
+         style="stop-color:white;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
        xlink:href="#linearGradient3149"
-       id="linearGradient2269"
+       id="linearGradient2126"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.466524,0,0,0.466525,38.65385,10.80199)"
+       x1="15.498499"
+       y1="9.4211226"
+       x2="24.240097"
+       y2="36.603138" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2239"
+       id="linearGradient2132"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.705322,0,0,0.705327,-58.76363,3.243275)"
+       x1="15.602553"
+       y1="1.5657365"
+       x2="15.602553"
+       y2="21.045444" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2146"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.466524,0,0,0.466525,38.65385,10.80199)"
+       x1="15.498499"
+       y1="9.4211226"
+       x2="24.240097"
+       y2="36.603138" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient2148"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       y2="34.774117"
+       x2="17.890068"
+       y1="0.6668244"
+       x1="17.890068"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient1999"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       id="linearGradient2857"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="18.507565"
+       x2="17.890068"
+       y1="2.197206"
+       x1="17.890068"
+       id="linearGradient1996"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient1994"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient1976">
+      <stop
+         id="stop1978"
+         offset="0"
+         style="stop-color:#73d216;stop-opacity:1;" />
+      <stop
+         id="stop1980"
+         offset="1"
+         style="stop-color:#5ca911;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2011"
        gradientUnits="userSpaceOnUse"
        x1="17.890068"
-       y1="0.6668244"
+       y1="8.0617304"
+       x2="17.890068"
+       y2="40.032413" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient2013"
+       gradientUnits="userSpaceOnUse"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3816"
+       id="radialGradient2015"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       y2="21.045444"
+       x2="15.602553"
+       y1="1.5657365"
+       x1="15.602553"
+       gradientTransform="matrix(0.705322,0,0,0.705327,-24.28038,0.710083)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2059"
+       xlink:href="#linearGradient2239"
+       inkscape:collect="always" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2147"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3816"
+       id="radialGradient2145"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2239"
+       id="linearGradient2143"
+       x1="15.602553"
+       y1="1.5657365"
+       x2="15.522223"
+       y2="33.483475"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.999824,0,0,0.999281,2.209264e-4,5.644055e-4)" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2141"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="11.024895"
+       x2="10.623409"
+       y1="2.7991772"
+       x1="4.5264969"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2139"
+       xlink:href="#linearGradient2804"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2124"
+       gradientUnits="userSpaceOnUse"
+       x1="17.890068"
+       y1="8.0617304"
        x2="17.890068"
-       y2="34.774117" />
+       y2="40.032413" />
+    <linearGradient
+       id="linearGradient2118">
+      <stop
+         style="stop-color:#73d216;stop-opacity:1;"
+         offset="0"
+         id="stop2120" />
+      <stop
+         style="stop-color:#5ca911;stop-opacity:1;"
+         offset="1"
+         id="stop2122" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient2110"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2804"
+       id="linearGradient2108"
+       x1="4.5264969"
+       y1="2.7991772"
+       x2="10.623409"
+       y2="11.024895"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient2106"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.493392,0,4.185903)"
+       r="5.7619157"
+       fy="5.3375292"
+       fx="10.99079"
+       cy="5.3375292"
+       cx="10.99079"
+       id="radialGradient2104"
+       xlink:href="#linearGradient5129"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(0.705322,0,0,0.705327,-24.28038,0.710083)"
+       gradientUnits="userSpaceOnUse"
+       y2="21.045444"
+       x2="15.602553"
+       y1="1.5657365"
+       x1="15.602553"
+       id="linearGradient2245"
+       xlink:href="#linearGradient2239"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.842757,0,0,-0.35721,19.80716,14.19321)"
+       r="6.6449099"
+       fy="10.457643"
+       fx="10.748654"
+       cy="10.457643"
+       cx="10.748654"
+       id="radialGradient2095"
+       xlink:href="#linearGradient3150"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient2087"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2167"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.004822,0,0,1.004822,-2.476351,-2.157242)"
+       x1="15.498499"
+       y1="9.4211226"
+       x2="24.240097"
+       y2="36.603138" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient2184"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient2189"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.789503,0,0,0.789503,-2.624255,-2.373563)"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2191"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.717731,0,0,0.71773,-1.34025,-1.112314)"
+       x1="15.498499"
+       y1="9.4211226"
+       x2="24.240097"
+       y2="36.603138" />
   </defs>
   <sodipodi:namedview
      id="base"
@@ -102,17 +777,19 @@
      borderopacity="1.0"
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
-     inkscape:zoom="25.992076"
-     inkscape:cx="20.3848"
-     inkscape:cy="9.8287529"
+     inkscape:zoom="14.928527"
+     inkscape:cx="26.286595"
+     inkscape:cy="13.181001"
      inkscape:document-units="px"
      inkscape:current-layer="layer1"
      showgrid="true"
      fill="#eeeeec"
-     inkscape:window-width="1268"
-     inkscape:window-height="968"
-     inkscape:window-x="6"
-     inkscape:window-y="21" />
+     inkscape:window-width="1434"
+     inkscape:window-height="844"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     height="24px"
+     width="24px" />
   <metadata
      id="metadata7">
     <rdf:RDF>
@@ -134,37 +811,17 @@
        sodipodi:rx="8.6620579"
        sodipodi:cy="19.008621"
        sodipodi:cx="31.112698"
-       id="path4318"
-       style="opacity:0.7;color:#000000;fill:url(#radialGradient3822);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       sodipodi:type="arc"
-       transform="matrix(1.385352,0,0,0.634953,-31.10204,6.430418)" />
-    <path
+       id="path1948"
+       style="color:black;fill:url(#radialGradient2184);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
        sodipodi:type="arc"
-       style="opacity:1;fill:url(#linearGradient2857);fill-opacity:1;fill-rule:evenodd;stroke:#418203;stroke-width:1.32699585;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path2245"
-       sodipodi:cx="17.890068"
-       sodipodi:cy="17.572527"
-       sodipodi:rx="13.932817"
-       sodipodi:ry="13.932817"
-       d="M 31.822886 17.572527 A 13.932817 13.932817 0 1 1  3.9572506,17.572527 A 13.932817 13.932817 0 1 1  31.822886 17.572527 z"
-       transform="matrix(0.75357,0,0,0.753592,-1.481423,-1.2422)" />
-    <image
-       id="image1323"
-       height="64.794617"
-       width="64.794617"
-       sodipodi:absref="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-       xlink:href="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-       x="-74"
-       y="-17" />
+       transform="matrix(1.269906,0,0,0.346338,-27.5102,14.41659)" />
     <path
-       sodipodi:type="arc"
-       style="opacity:0.5;fill:url(#linearGradient2269);fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.46676958;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path3145"
-       sodipodi:cx="17.890068"
-       sodipodi:cy="17.572527"
-       sodipodi:rx="13.932817"
-       sodipodi:ry="13.932817"
-       d="M 31.822886 17.572527 A 13.932817 13.932817 0 1 1  3.9572506,17.572527 A 13.932817 13.932817 0 1 1  31.822886 17.572527 z"
-       transform="matrix(0.681795,0,0,0.681747,-0.197796,2.041858e-2)" />
+       style="fill:url(#linearGradient2189);fill-opacity:1;fill-rule:evenodd;stroke:#306300;stroke-width:0.99999911;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 22.500011,11.499997 C 22.500011,17.571995 17.57201,22.499994 11.500011,22.499994 C 5.428011,22.499994 0.50001162,17.571995 0.50001162,11.499997 C 0.50001162,5.4279975 5.428011,0.4999987 11.500011,0.4999987 C 17.57201,0.4999987 22.500011,5.4279975 22.500011,11.499997 z "
+       id="path4331" />
+    <path
+       style="opacity:0.6;fill:url(#linearGradient2191);fill-opacity:1;fill-rule:evenodd;stroke:white;stroke-width:0.99999809;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 21.500009,11.499995 C 21.500009,17.019992 17.020007,21.499992 11.500005,21.499992 C 5.9800027,21.499992 1.4999988,17.019992 1.4999988,11.499995 C 1.4999988,5.9799971 5.9800027,1.4999992 11.500005,1.4999992 C 17.020007,1.4999992 21.500009,5.9799971 21.500009,11.499995 z "
+       id="path4333" />
   </g>
 </svg>
--- a/pidgin/pixmaps/status/22/scalable/away.svg	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/status/22/scalable/away.svg	Mon Jun 18 01:48:35 2007 +0000
@@ -7,23 +7,47 @@
    xmlns:svg="http://www.w3.org/2000/svg"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/s odipodi-0.dtd"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    width="24"
    height="24"
    id="svg1331"
    sodipodi:version="0.32"
-   inkscape:version="0.43"
+   inkscape:version="0.44.1"
    version="1.0"
-   inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/status/away.png"
+   inkscape:export-filename="/home/hbons/Desktop/away.png"
    inkscape:export-xdpi="90"
    inkscape:export-ydpi="90"
-   sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/status/22/scalable"
-   sodipodi:docname="away22.svg">
+   sodipodi:docbase="/home/hbons/Desktop/experiment/status/22/scalable"
+   sodipodi:docname="away.svg">
   <defs
      id="defs1333">
     <linearGradient
        inkscape:collect="always"
+       id="linearGradient2811">
+      <stop
+         style="stop-color:white;stop-opacity:1;"
+         offset="0"
+         id="stop2813" />
+      <stop
+         style="stop-color:white;stop-opacity:0;"
+         offset="1"
+         id="stop2815" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient5129">
+      <stop
+         style="stop-color:white;stop-opacity:1;"
+         offset="0"
+         id="stop5131" />
+      <stop
+         style="stop-color:white;stop-opacity:0;"
+         offset="1"
+         id="stop5133" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
        id="linearGradient3816">
       <stop
          style="stop-color:#000000;stop-opacity:1;"
@@ -85,10 +109,175 @@
        id="linearGradient2245"
        x1="15.602553"
        y1="1.5657365"
-       x2="15.522223"
+       x2="15.602553"
+       y2="21.045444"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.705322,0,0,0.705327,-24.28038,0.710083)" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5129"
+       id="radialGradient5135"
+       cx="10.99079"
+       cy="5.3375292"
+       fx="10.99079"
+       fy="5.3375292"
+       r="5.7619157"
+       gradientTransform="matrix(1,0,0,0.493392,0,4.185903)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient2818"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="11.024895"
+       x2="10.623409"
+       y1="2.7991772"
+       x1="4.5264969"
+       id="linearGradient2810"
+       xlink:href="#linearGradient2804"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       id="linearGradient2857"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient3149"
+       inkscape:collect="always">
+      <stop
+         id="stop3151"
+         offset="0"
+         style="stop-color:#eeeeec;stop-opacity:1;" />
+      <stop
+         id="stop3153"
+         offset="1"
+         style="stop-color:#eeeeec;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2851">
+      <stop
+         id="stop2853"
+         offset="0"
+         style="stop-color:#73d216;stop-opacity:1;" />
+      <stop
+         id="stop2855"
+         offset="1"
+         style="stop-color:#5ca911;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       y2="40.032413"
+       x2="17.890068"
+       y1="8.0617304"
+       x1="17.890068"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2269"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2804"
+       inkscape:collect="always">
+      <stop
+         id="stop2806"
+         offset="0"
+         style="stop-color:white;stop-opacity:1;" />
+      <stop
+         id="stop2808"
+         offset="1"
+         style="stop-color:white;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2812"
+       inkscape:collect="always">
+      <stop
+         id="stop2814"
+         offset="0"
+         style="stop-color:#2e3436;stop-opacity:1;" />
+      <stop
+         id="stop2816"
+         offset="1"
+         style="stop-color:#2e3436;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2804"
+       id="linearGradient1983"
+       gradientUnits="userSpaceOnUse"
+       x1="4.5264969"
+       y1="2.7991772"
+       x2="10.623409"
+       y2="11.024895" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient1985"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       gradientTransform="matrix(0.999824,0,0,0.999281,2.209264e-4,5.644055e-4)"
+       gradientUnits="userSpaceOnUse"
        y2="33.483475"
+       x2="15.522223"
+       y1="1.5657365"
+       x1="15.602553"
+       id="linearGradient2040"
+       xlink:href="#linearGradient2239"
+       inkscape:collect="always" />
+    <radialGradient
        gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.705322,0,0,0.705327,0.719621,0.710083)" />
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient2032"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3816"
+       id="radialGradient2057"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2239"
+       id="linearGradient2059"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.705322,0,0,0.705327,-24.28038,0.710083)"
+       x1="15.602553"
+       y1="1.5657365"
+       x2="15.602553"
+       y2="21.045444" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2811"
+       id="radialGradient2817"
+       cx="5.2511673"
+       cy="7.3335675"
+       fx="5.2511673"
+       fy="7.3335675"
+       r="0.82651663"
+       gradientTransform="matrix(1,0,0,1.337946,0,-2.478349)"
+       gradientUnits="userSpaceOnUse" />
   </defs>
   <sodipodi:namedview
      id="base"
@@ -97,18 +286,18 @@
      borderopacity="1.0"
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
-     inkscape:zoom="19.69831"
-     inkscape:cx="17.254293"
-     inkscape:cy="10.464226"
+     inkscape:zoom="13.928809"
+     inkscape:cx="38.913091"
+     inkscape:cy="9.6136547"
      inkscape:current-layer="layer1"
      showgrid="true"
      inkscape:grid-bbox="true"
      inkscape:document-units="px"
      fill="#729fcf"
-     inkscape:window-width="1268"
-     inkscape:window-height="972"
-     inkscape:window-x="6"
-     inkscape:window-y="21" />
+     inkscape:window-width="1434"
+     inkscape:window-height="844"
+     inkscape:window-x="0"
+     inkscape:window-y="0" />
   <metadata
      id="metadata1336">
     <rdf:RDF>
@@ -130,63 +319,162 @@
        sodipodi:rx="8.6620579"
        sodipodi:cy="19.008621"
        sodipodi:cx="31.112698"
-       id="path4318"
-       style="opacity:0.7;color:#000000;fill:url(#radialGradient3822);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       id="path1948"
+       style="color:black;fill:url(#radialGradient1985);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
        sodipodi:type="arc"
-       transform="matrix(1.385352,0,0,0.634953,-31.10204,6.430418)" />
+       transform="matrix(1.269906,0,0,0.346338,-27.5102,14.41659)" />
     <path
        sodipodi:type="arc"
-       style="opacity:1;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:evenodd;stroke:#204a87;stroke-width:1.36561811px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       id="path1339"
+       style="color:black;fill:#729fcf;fill-opacity:1;fill-rule:evenodd;stroke:#173867;stroke-width:1.3043046px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       id="path1951"
        sodipodi:cx="15.590227"
        sodipodi:cy="16.57217"
        sodipodi:rx="14.345175"
        sodipodi:ry="14.345175"
        d="M 29.935402 16.57217 A 14.345175 14.345175 0 1 1  1.2450523,16.57217 A 14.345175 14.345175 0 1 1  29.935402 16.57217 z"
-       transform="matrix(0.732268,0,0,0.732268,0.582335,-0.13671)" />
+       transform="matrix(0.766665,0,0,0.766715,-0.450429,-1.204777)" />
     <path
        sodipodi:type="arc"
-       style="opacity:1;color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#204a87;stroke-width:1.68800032px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       id="path1341"
+       style="fill:#8ab0d7;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="path2788"
+       sodipodi:cx="-3.8088531"
+       sodipodi:cy="3.303823"
+       sodipodi:rx="3.1932809"
+       sodipodi:ry="3.3471739"
+       d="M -0.61557221 3.303823 A 3.1932809 3.3471739 0 1 1  -7.0021341,3.303823 A 3.1932809 3.3471739 0 1 1  -0.61557221 3.303823 z"
+       transform="matrix(3.246937,0,0,3.097864,23.99872,1.396119)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:0.40340911;color:black;fill:#babdb6;fill-opacity:1;fill-rule:evenodd;stroke:#173867;stroke-width:1.59390604px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       id="path1954"
        sodipodi:cx="15.590227"
        sodipodi:cy="16.57217"
        sodipodi:rx="14.345175"
        sodipodi:ry="14.345175"
        d="M 29.935402 16.57217 A 14.345175 14.345175 0 1 1  1.2450523,16.57217 A 14.345175 14.345175 0 1 1  29.935402 16.57217 z"
-       transform="matrix(0.592417,0,0,0.592416,2.763254,2.183203)" />
+       transform="matrix(0.627389,0,0,0.627389,1.718859,1.102807)" />
     <path
        sodipodi:type="arc"
-       style="opacity:1;color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#2e3436;stroke-width:7.84294748px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       id="path2216"
-       sodipodi:cx="15.590227"
-       sodipodi:cy="16.57217"
-       sodipodi:rx="14.345175"
-       sodipodi:ry="14.345175"
-       d="M 29.935402 16.57217 A 14.345175 14.345175 0 1 1  1.2450523,16.57217 A 14.345175 14.345175 0 1 1  29.935402 16.57217 z"
-       transform="matrix(0.127505,0,0,0.127505,10.01337,9.888169)" />
+       style="fill:#dcdcd8;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="path2796"
+       sodipodi:cx="6.0403023"
+       sodipodi:cy="7.5551186"
+       sodipodi:rx="1.615877"
+       sodipodi:ry="1.3273276"
+       d="M 7.6561793 7.5551186 A 1.615877 1.3273276 0 1 1  4.4244252,7.5551186 A 1.615877 1.3273276 0 1 1  7.6561793 7.5551186 z"
+       transform="matrix(5.2603,0,0,6.403843,-20.2738,-36.88179)" />
     <path
-       style="opacity:0.5;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient2245);stroke-width:0.99999976px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       d="M 21.51933,11.9953 C 21.51933,17.24738 17.256803,21.509937 12.004759,21.509937 C 6.7527164,21.509937 2.4901888,17.24738 2.4901888,11.9953 C 2.4901888,6.7432209 6.7527164,2.4806637 12.004759,2.4806637 C 17.256803,2.4806637 21.51933,6.7432209 21.51933,11.9953 z "
-       id="path2220" />
+       sodipodi:type="arc"
+       style="opacity:0.76704544;fill:none;fill-opacity:1;stroke:url(#linearGradient1983);stroke-width:0.52440464;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="path2802"
+       sodipodi:cx="7.5"
+       sodipodi:cy="7"
+       sodipodi:rx="5.5"
+       sodipodi:ry="5"
+       d="M 13 7 A 5.5 5 0 1 1  2,7 A 5.5 5 0 1 1  13 7 z"
+       transform="matrix(1.818182,0,0,2,-2.136362,-2.499999)" />
     <path
        sodipodi:type="arc"
-       style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path1588"
-       sodipodi:cx="20.264311"
-       sodipodi:cy="14.476474"
-       sodipodi:rx="2.9448855"
-       sodipodi:ry="0.78724658"
-       d="M 23.209196 14.476474 A 2.9448855 0.78724658 0 1 1  17.319425,14.476474 A 2.9448855 0.78724658 0 1 1  23.209196 14.476474 z"
-       transform="matrix(0.624124,-0.624126,1.00058,1.000585,-12.1323,7.162558)" />
-    <path
-       sodipodi:type="arc"
-       style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path2476"
-       sodipodi:cx="20.264311"
-       sodipodi:cy="14.476474"
-       sodipodi:rx="2.9448855"
-       sodipodi:ry="0.78724658"
-       d="M 23.209196 14.476474 A 2.9448855 0.78724658 0 1 1  17.319425,14.476474 A 2.9448855 0.78724658 0 1 1  23.209196 14.476474 z"
-       transform="matrix(0.624125,0.624124,1.000581,-1.00058,-12.13234,16.83743)" />
+       style="fill:url(#radialGradient2817);fill-opacity:1.0;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="path2852"
+       sodipodi:cx="6.0403023"
+       sodipodi:cy="7.5551186"
+       sodipodi:rx="1.615877"
+       sodipodi:ry="1.3273276"
+       d="M 4.835244,8.4394021 A 1.615877,1.3273276 0 0 1 6.0776839,6.2281462 L 6.0403023,7.5551186 z"
+       transform="matrix(3.941577,0,0,4.521472,-12.44011,-23.15852)"
+       sodipodi:start="2.4124729"
+       sodipodi:end="4.735525" />
+    <rect
+       style="fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect1926"
+       width="1"
+       height="1"
+       x="10"
+       y="-13"
+       transform="matrix(0,1,-1,0,0,0)" />
+    <rect
+       style="fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect1928"
+       width="1"
+       height="1"
+       x="12"
+       y="-13"
+       transform="matrix(0,1,-1,0,0,0)" />
+    <rect
+       style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2838"
+       width="3"
+       height="3"
+       x="10"
+       y="-13"
+       rx="1.5"
+       ry="1.5"
+       transform="matrix(0,1,-1,0,0,0)" />
+    <rect
+       style="fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect1987"
+       width="1"
+       height="1"
+       x="11"
+       y="-12"
+       rx="0.5"
+       ry="0.5"
+       transform="matrix(0,1,-1,0,0,0)" />
+    <rect
+       style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect1991"
+       width="1"
+       height="1"
+       x="9"
+       y="-14"
+       transform="matrix(0,1,-1,0,0,0)" />
+    <rect
+       style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect1993"
+       width="1"
+       height="1"
+       x="8"
+       y="-15"
+       transform="matrix(0,1,-1,0,0,0)" />
+    <rect
+       style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect1995"
+       width="1"
+       height="1"
+       x="7"
+       y="-16"
+       transform="matrix(0,1,-1,0,0,0)" />
+    <rect
+       style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect1999"
+       width="1"
+       height="1"
+       x="-13.953762"
+       y="-14"
+       transform="matrix(0,-1,-1,0,0,0)" />
+    <rect
+       style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2001"
+       width="1"
+       height="1"
+       x="-14.953762"
+       y="-15"
+       transform="matrix(0,-1,-1,0,0,0)" />
+    <rect
+       style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2003"
+       width="1"
+       height="1"
+       x="-15.953762"
+       y="-16"
+       transform="matrix(0,-1,-1,0,0,0)" />
+    <rect
+       style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect1932"
+       width="1"
+       height="1.0102224"
+       x="11"
+       y="10.989778" />
   </g>
 </svg>
--- a/pidgin/pixmaps/status/22/scalable/offline.svg	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/status/22/scalable/offline.svg	Mon Jun 18 01:48:35 2007 +0000
@@ -7,16 +7,16 @@
    xmlns:svg="http://www.w3.org/2000/svg"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/s odipodi-0.dtd"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    width="24"
    height="24"
    id="svg2"
    sodipodi:version="0.32"
-   inkscape:version="0.43"
+   inkscape:version="0.44.1"
    version="1.0"
-   sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/status/22/scalable"
-   sodipodi:docname="offline22.svg"
+   sodipodi:docbase="/home/hbons/Desktop/experiment/status/22/scalable"
+   sodipodi:docname="offline.svg"
    inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/status/offline.png"
    inkscape:export-xdpi="90"
    inkscape:export-ydpi="90">
@@ -24,6 +24,30 @@
      id="defs4">
     <linearGradient
        inkscape:collect="always"
+       id="linearGradient3034">
+      <stop
+         style="stop-color:#babdb6;stop-opacity:1"
+         offset="0"
+         id="stop3036" />
+      <stop
+         style="stop-color:#d3d7cf;stop-opacity:0;"
+         offset="1"
+         id="stop3038" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2784">
+      <stop
+         style="stop-color:#babdb6;stop-opacity:1;"
+         offset="0"
+         id="stop2786" />
+      <stop
+         style="stop-color:#babdb6;stop-opacity:0;"
+         offset="1"
+         id="stop2788" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
        id="linearGradient3816">
       <stop
          style="stop-color:#000000;stop-opacity:1;"
@@ -108,7 +132,1189 @@
        x1="12.00096"
        y1="18.000015"
        x2="12.00096"
-       y2="12.421011" />
+       y2="12.421011"
+       gradientTransform="translate(-14.51828,-0.483273)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2784"
+       id="linearGradient2790"
+       x1="11.999999"
+       y1="17.358862"
+       x2="11.999999"
+       y2="11.173834"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient3286"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3816"
+       id="radialGradient3002"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3150"
+       id="radialGradient3201"
+       cx="10.748654"
+       cy="10.457643"
+       fx="10.748654"
+       fy="10.457643"
+       r="6.6449099"
+       gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2239"
+       id="linearGradient2245"
+       x1="15.602553"
+       y1="1.5657365"
+       x2="15.602553"
+       y2="21.045444"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.705322,0,0,0.705327,-24.28038,0.710083)" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5129"
+       id="radialGradient3210"
+       cx="10.99079"
+       cy="5.3375292"
+       fx="10.99079"
+       fy="5.3375292"
+       r="5.7619157"
+       gradientTransform="matrix(1,0,0,0.493392,0,4.185903)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient3212"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="11.024895"
+       x2="10.623409"
+       y1="2.7991772"
+       x1="4.5264969"
+       id="linearGradient3214"
+       xlink:href="#linearGradient2804"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       id="linearGradient3216"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient3224">
+      <stop
+         id="stop3226"
+         offset="0"
+         style="stop-color:#73d216;stop-opacity:1;" />
+      <stop
+         id="stop3228"
+         offset="1"
+         style="stop-color:#5ca911;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       y2="40.032413"
+       x2="17.890068"
+       y1="8.0617304"
+       x1="17.890068"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3230"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2804"
+       id="linearGradient1983"
+       gradientUnits="userSpaceOnUse"
+       x1="4.5264969"
+       y1="2.7991772"
+       x2="10.623409"
+       y2="11.024895" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient3245"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       gradientTransform="matrix(0.999824,0,0,0.999281,2.209264e-4,5.644055e-4)"
+       gradientUnits="userSpaceOnUse"
+       y2="33.483475"
+       x2="15.522223"
+       y1="1.5657365"
+       x1="15.602553"
+       id="linearGradient3247"
+       xlink:href="#linearGradient2239"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient3249"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3816"
+       id="radialGradient3251"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2239"
+       id="linearGradient2059"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.705322,0,0,0.705327,-24.28038,0.710083)"
+       x1="15.602553"
+       y1="1.5657365"
+       x2="15.602553"
+       y2="21.045444" />
+    <linearGradient
+       y2="32.896225"
+       x2="11.507221"
+       y1="4.5275822"
+       x1="6.6158633"
+       gradientTransform="matrix(1.535977,0,0,1.528473,-0.804927,-0.69647)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2210"
+       xlink:href="#linearGradient2239"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="10.792614"
+       x2="9.0812168"
+       y1="-0.76356995"
+       x1="3.3119085"
+       gradientTransform="matrix(2.177693,0,0,2.167044,-2.372032,-2.235246)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2208"
+       xlink:href="#linearGradient2186"
+       inkscape:collect="always" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2898"
+       id="radialGradient2141"
+       cx="4.8470273"
+       cy="6.9473476"
+       fx="4.8470273"
+       fy="6.9473476"
+       r="0.8078171"
+       gradientTransform="matrix(3.018423,0.664359,-1.388844,4.257661,-0.134567,-26.02469)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient2149"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2186"
+       id="linearGradient2157"
+       x1="9.2594385"
+       y1="-1.5641226"
+       x2="11.226587"
+       y2="17.697369"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.684526,0,0,0.687171,-0.20455,-0.253325)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2239"
+       id="linearGradient2165"
+       x1="8.7505674"
+       y1="4.5934086"
+       x2="31.18539"
+       y2="39.834526"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.482882,0,0,0.482874,0.269812,0.26982)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2167"
+       gradientUnits="userSpaceOnUse"
+       x1="17.890068"
+       y1="8.0617304"
+       x2="17.890068"
+       y2="40.032413" />
+    <linearGradient
+       id="linearGradient2169">
+      <stop
+         style="stop-color:#73d216;stop-opacity:1;"
+         offset="0"
+         id="stop2171" />
+      <stop
+         style="stop-color:#5ca911;stop-opacity:1;"
+         offset="1"
+         id="stop2173" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3816"
+       id="radialGradient2187"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.914124,0,0,1.631747,2.671799,-12.00863)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient2857"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient2851">
+      <stop
+         style="stop-color:#73d216;stop-opacity:1;"
+         offset="0"
+         id="stop2853" />
+      <stop
+         style="stop-color:#5ca911;stop-opacity:1;"
+         offset="1"
+         id="stop2855" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3149">
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:1;"
+         offset="0"
+         id="stop3151" />
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:0;"
+         offset="1"
+         id="stop3153" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3816"
+       id="radialGradient1988"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient3155"
+       x1="17.890068"
+       y1="8.3091545"
+       x2="17.890068"
+       y2="36.574547"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       y2="11.024895"
+       x2="10.623409"
+       y1="2.7991772"
+       x1="4.5264969"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3007"
+       xlink:href="#linearGradient2804"
+       inkscape:collect="always" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient3005"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2812">
+      <stop
+         style="stop-color:#2e3436;stop-opacity:1;"
+         offset="0"
+         id="stop2814" />
+      <stop
+         style="stop-color:#2e3436;stop-opacity:0;"
+         offset="1"
+         id="stop2816" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2804">
+      <stop
+         style="stop-color:white;stop-opacity:1;"
+         offset="0"
+         id="stop2806" />
+      <stop
+         style="stop-color:white;stop-opacity:0;"
+         offset="1"
+         id="stop2808" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2949"
+       gradientUnits="userSpaceOnUse"
+       x1="17.890068"
+       y1="8.0617304"
+       x2="17.890068"
+       y2="40.032413" />
+    <linearGradient
+       id="linearGradient2951">
+      <stop
+         style="stop-color:#73d216;stop-opacity:1;"
+         offset="0"
+         id="stop2953" />
+      <stop
+         style="stop-color:#5ca911;stop-opacity:1;"
+         offset="1"
+         id="stop2955" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient2963"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2804"
+       id="linearGradient2810"
+       x1="4.5264969"
+       y1="2.7991772"
+       x2="10.623409"
+       y2="11.024895"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient2818"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       id="linearGradient1955"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientTransform="matrix(0.914124,0,0,1.631747,2.671799,-12.00863)"
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient1953"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient1935">
+      <stop
+         id="stop1937"
+         offset="0"
+         style="stop-color:#73d216;stop-opacity:1;" />
+      <stop
+         id="stop1939"
+         offset="1"
+         style="stop-color:#5ca911;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       y2="40.032413"
+       x2="17.890068"
+       y1="8.0617304"
+       x1="17.890068"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2269"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="36.603138"
+       x2="24.240097"
+       y1="9.4211226"
+       x1="15.498499"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient4740"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient4738"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2898"
+       id="radialGradient1990"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(3.018423,0.664359,-1.388844,4.257661,-0.134567,-26.02469)"
+       cx="4.8470273"
+       cy="6.9473476"
+       fx="4.8470273"
+       fy="6.9473476"
+       r="0.8078171" />
+    <linearGradient
+       y2="21.045444"
+       x2="15.602553"
+       y1="1.5657365"
+       x1="15.602553"
+       gradientTransform="matrix(0.705322,0,0,0.705327,8.71963,7.710084)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2073"
+       xlink:href="#linearGradient2239"
+       inkscape:collect="always" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2057"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3816"
+       id="radialGradient2032"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2239"
+       id="linearGradient2040"
+       x1="15.602553"
+       y1="1.5657365"
+       x2="15.522223"
+       y2="33.483475"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.999824,0,0,0.999281,2.209264e-4,5.644055e-4)" />
+    <linearGradient
+       y2="11.024895"
+       x2="10.623409"
+       y1="2.7991772"
+       x1="4.5264969"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2100"
+       xlink:href="#linearGradient2804"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2086"
+       gradientUnits="userSpaceOnUse"
+       x1="17.890068"
+       y1="8.0617304"
+       x2="17.890068"
+       y2="40.032413" />
+    <linearGradient
+       id="linearGradient2080">
+      <stop
+         style="stop-color:#73d216;stop-opacity:1;"
+         offset="0"
+         id="stop2082" />
+      <stop
+         style="stop-color:#5ca911;stop-opacity:1;"
+         offset="1"
+         id="stop2084" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient2072"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2804"
+       id="linearGradient2070"
+       x1="4.5264969"
+       y1="2.7991772"
+       x2="10.623409"
+       y2="11.024895"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient2068"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.493392,0,4.185903)"
+       r="5.7619157"
+       fy="5.3375292"
+       fx="10.99079"
+       cy="5.3375292"
+       cx="10.99079"
+       id="radialGradient5135"
+       xlink:href="#linearGradient5129"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.842757,0,0,-0.35721,19.80716,14.19321)"
+       r="6.6449099"
+       fy="10.457643"
+       fx="10.748654"
+       cy="10.457643"
+       cx="10.748654"
+       id="radialGradient2921"
+       xlink:href="#linearGradient3150"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient5129"
+       inkscape:collect="always">
+      <stop
+         id="stop5131"
+         offset="0"
+         style="stop-color:white;stop-opacity:1;" />
+      <stop
+         id="stop5133"
+         offset="1"
+         style="stop-color:white;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2126"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.466524,0,0,0.466525,38.65385,10.80199)"
+       x1="15.498499"
+       y1="9.4211226"
+       x2="24.240097"
+       y2="36.603138" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2239"
+       id="linearGradient2132"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.705322,0,0,0.705327,-58.76363,3.243275)"
+       x1="15.602553"
+       y1="1.5657365"
+       x2="15.602553"
+       y2="21.045444" />
+    <linearGradient
+       id="linearGradient2239"
+       inkscape:collect="always">
+      <stop
+         id="stop2241"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop2243"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2186"
+       inkscape:collect="always">
+      <stop
+         id="stop2188"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop2190"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2898"
+       inkscape:collect="always">
+      <stop
+         id="stop2900"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         id="stop2902"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2186"
+       id="linearGradient3014"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.177693,0,0,2.167044,21.62797,-2.235244)"
+       x1="3.3119085"
+       y1="-0.76356995"
+       x2="9.0812168"
+       y2="10.792614" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2239"
+       id="linearGradient3016"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.535977,0,0,1.528473,23.19507,-0.696468)"
+       x1="6.6158633"
+       y1="4.5275822"
+       x2="11.507221"
+       y2="32.896225" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient3021"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3034"
+       id="linearGradient3040"
+       x1="11.500003"
+       y1="19.000008"
+       x2="11.500003"
+       y2="9.3821249"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3034"
+       id="linearGradient3044"
+       gradientUnits="userSpaceOnUse"
+       x1="11.500003"
+       y1="19.000008"
+       x2="11.500003"
+       y2="9.3821249"
+       gradientTransform="matrix(0.857143,0,0,0.857143,1.642855,1.64286)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3034"
+       id="linearGradient3048"
+       gradientUnits="userSpaceOnUse"
+       x1="11.500003"
+       y1="19.000008"
+       x2="11.500003"
+       y2="9.3821249" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2062"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       gradientTransform="matrix(1.076595,0,0,1.076595,-34.76035,-3.418494)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2253"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="36.603138"
+       x2="24.240097"
+       y1="9.4211226"
+       x1="15.498499"
+       gradientTransform="matrix(1.004822,0,0,1.004822,-33.47635,-2.157242)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2056"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2246">
+      <stop
+         style="stop-color:#73d216;stop-opacity:1;"
+         offset="0"
+         id="stop2248" />
+      <stop
+         style="stop-color:#5ca911;stop-opacity:1;"
+         offset="1"
+         id="stop2250" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3816"
+       id="radialGradient1983"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2236"
+       x1="17.890068"
+       y1="8.3091545"
+       x2="17.890068"
+       y2="36.574547"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient3025"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="11.024895"
+       x2="10.623409"
+       y1="2.7991772"
+       x1="4.5264969"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2232"
+       xlink:href="#linearGradient2804"
+       inkscape:collect="always" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2230"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2215"
+       gradientUnits="userSpaceOnUse"
+       x1="17.890068"
+       y1="8.0617304"
+       x2="17.890068"
+       y2="40.032413" />
+    <linearGradient
+       id="linearGradient2209">
+      <stop
+         style="stop-color:#73d216;stop-opacity:1;"
+         offset="0"
+         id="stop2211" />
+      <stop
+         style="stop-color:#5ca911;stop-opacity:1;"
+         offset="1"
+         id="stop2213" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient2206"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2804"
+       id="linearGradient2204"
+       x1="4.5264969"
+       y1="2.7991772"
+       x2="10.623409"
+       y2="11.024895"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient2202"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(3.018423,0.664359,-1.388844,4.257661,-0.134567,-26.02469)"
+       r="0.8078171"
+       fy="6.9473476"
+       fx="4.8470273"
+       cy="6.9473476"
+       cx="4.8470273"
+       id="radialGradient2904"
+       xlink:href="#linearGradient2898"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       id="linearGradient2199"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientTransform="matrix(0.914124,-3.896132e-15,-2.475021e-18,1.631747,2.671799,-12.00863)"
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient2197"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2191">
+      <stop
+         id="stop2193"
+         offset="0"
+         style="stop-color:#73d216;stop-opacity:1;" />
+      <stop
+         id="stop2195"
+         offset="1"
+         style="stop-color:#5ca911;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       y2="40.032413"
+       x2="17.890068"
+       y1="8.0617304"
+       x1="17.890068"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2189"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="36.603138"
+       x2="24.240097"
+       y1="9.4211226"
+       x1="15.498499"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2187"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2184"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2176"
+       gradientUnits="userSpaceOnUse"
+       x1="15.498499"
+       y1="9.4211226"
+       x2="24.240097"
+       y2="36.603138"
+       gradientTransform="matrix(1.004822,0,0,1.004822,-2.476351,-2.157242)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient1986"
+       gradientUnits="userSpaceOnUse"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807"
+       gradientTransform="matrix(1.076595,0,0,1.076595,-3.760351,-3.418494)" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2898"
+       id="radialGradient2173"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(3.018423,0.664359,-1.388844,4.257661,-0.134567,-26.02469)"
+       cx="4.8470273"
+       cy="6.9473476"
+       fx="4.8470273"
+       fy="6.9473476"
+       r="0.8078171" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient1992"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       y2="21.045444"
+       x2="15.602553"
+       y1="1.5657365"
+       x1="15.602553"
+       gradientTransform="matrix(0.705322,0,0,0.705327,8.71963,7.710084)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2170"
+       xlink:href="#linearGradient2239"
+       inkscape:collect="always" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2167"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3816"
+       id="radialGradient2165"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2239"
+       id="linearGradient2163"
+       x1="15.602553"
+       y1="1.5657365"
+       x2="15.522223"
+       y2="33.483475"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.999824,0,0,0.999281,2.209264e-4,5.644055e-4)" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1985"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="11.024895"
+       x2="10.623409"
+       y1="2.7991772"
+       x1="4.5264969"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2160"
+       xlink:href="#linearGradient2804"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2158"
+       gradientUnits="userSpaceOnUse"
+       x1="17.890068"
+       y1="8.0617304"
+       x2="17.890068"
+       y2="40.032413" />
+    <linearGradient
+       id="linearGradient2151">
+      <stop
+         style="stop-color:#73d216;stop-opacity:1;"
+         offset="0"
+         id="stop2153" />
+      <stop
+         style="stop-color:#5ca911;stop-opacity:1;"
+         offset="1"
+         id="stop2155" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient2149"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2804"
+       id="linearGradient2147"
+       x1="4.5264969"
+       y1="2.7991772"
+       x2="10.623409"
+       y2="11.024895"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient2144"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.493392,0,4.185903)"
+       r="5.7619157"
+       fy="5.3375292"
+       fx="10.99079"
+       cy="5.3375292"
+       cx="10.99079"
+       id="radialGradient2142"
+       xlink:href="#linearGradient5129"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.842757,0,0,-0.35721,19.80716,14.19321)"
+       r="6.6449099"
+       fy="10.457643"
+       fx="10.748654"
+       cy="10.457643"
+       cx="10.748654"
+       id="radialGradient2035"
+       xlink:href="#linearGradient3150"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2127"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.466524,0,0,0.466525,38.65385,10.80199)"
+       x1="15.498499"
+       y1="9.4211226"
+       x2="24.240097"
+       y2="36.603138" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2239"
+       id="linearGradient2125"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.705322,0,0,0.705327,-58.76363,3.243275)"
+       x1="15.602553"
+       y1="1.5657365"
+       x2="15.602553"
+       y2="21.045444" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2146"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.466524,0,0,0.466525,38.65385,10.80199)"
+       x1="15.498499"
+       y1="9.4211226"
+       x2="24.240097"
+       y2="36.603138" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient2148"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       gradientTransform="matrix(1.40375,0,0,1.403934,-1.668488,-1.296374)"
+       y2="9.1482677"
+       x2="12.00096"
+       y1="17.203793"
+       x1="12.00096"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2121"
+       xlink:href="#linearGradient2235"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="14.895812"
+       x2="11.802028"
+       y1="1.9986149"
+       x1="11.802028"
+       id="linearGradient2119"
+       xlink:href="#linearGradient2225"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
+       r="6.6449099"
+       fy="10.457643"
+       fx="10.748654"
+       cy="10.457643"
+       cx="10.748654"
+       id="radialGradient2105"
+       xlink:href="#linearGradient3150"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient2097"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2225"
+       id="linearGradient2268"
+       gradientUnits="userSpaceOnUse"
+       x1="11.802028"
+       y1="1.9986149"
+       x2="11.802028"
+       y2="14.895812" />
   </defs>
   <sodipodi:namedview
      id="base"
@@ -118,16 +1324,18 @@
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
      inkscape:zoom="20.899939"
-     inkscape:cx="21.212814"
-     inkscape:cy="11.149734"
+     inkscape:cx="22.169755"
+     inkscape:cy="10.589231"
      inkscape:document-units="px"
      inkscape:current-layer="layer1"
      showgrid="true"
      fill="#888a85"
-     inkscape:window-width="1268"
-     inkscape:window-height="971"
-     inkscape:window-x="6"
-     inkscape:window-y="21" />
+     inkscape:window-width="1434"
+     inkscape:window-height="844"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     showguides="true"
+     inkscape:guide-bbox="true" />
   <metadata
      id="metadata7">
     <rdf:RDF>
@@ -149,39 +1357,29 @@
        sodipodi:rx="8.6620579"
        sodipodi:cy="19.008621"
        sodipodi:cx="31.112698"
-       id="path4318"
-       style="opacity:0.7;color:#000000;fill:url(#radialGradient3822);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       id="path1948"
+       style="color:black;fill:url(#radialGradient3021);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
        sodipodi:type="arc"
-       transform="matrix(1.385352,0,0,0.634953,-31.10204,6.430418)" />
+       transform="matrix(1.269906,0,0,0.346338,-27.5102,14.41659)" />
     <path
-       style="fill:#888a85;fill-opacity:1;stroke:#555753;stroke-width:0.99999809;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 19.424962,19.424965 C 15.325526,23.524403 8.6720624,23.525096 4.5734814,19.426514 C 0.47490009,15.327931 0.47559413,8.6744652 4.5750306,4.5750271 C 8.6744668,0.4755893 15.32793,0.47489516 19.426511,4.573478 C 23.525092,8.6720606 23.524399,15.325527 19.424962,19.424965 z "
+       style="fill:#888a85;fill-opacity:1;stroke:#2e3436;stroke-width:0.99999821;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 19.27853,19.278538 C 14.983883,23.573188 8.0135883,23.573914 3.719837,19.280161 C -0.57391464,14.986408 -0.57318755,8.0161106 3.72146,3.7214613 C 8.0161072,-0.57318761 14.986402,-0.57391481 19.280153,3.7198384 C 23.573904,8.0135915 23.573178,14.983889 19.27853,19.278538 z "
        id="path2187" />
     <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-1.0137641"
-       inkscape:original="M 12 1.5 C 9.311882 1.5002804 6.612218 2.5127812 4.5625 4.5625 C 0.46306353 8.6619381 0.46391853 15.338917 4.5625 19.4375 C 8.661081 23.536082 15.338065 23.536938 19.4375 19.4375 C 23.536937 15.338062 23.53608 8.6610824 19.4375 4.5625 C 17.388209 2.5132086 14.688118 1.4997196 12 1.5 z "
-       xlink:href="#path2187"
-       style="fill:url(#linearGradient2231);fill-opacity:1.0;stroke:#ffffff;stroke-width:0.99999809;stroke-miterlimit:4;stroke-opacity:1;opacity:0.4"
-       id="path2215"
-       inkscape:href="#path2187"
-       d="M 12,2.5 C 9.5663798,2.5002539 7.1342728,3.4282024 5.28125,5.28125 C 1.5710546,8.9914951 1.5718911,15.009341 5.28125,18.71875 C 8.9905967,22.428146 15.008567,22.428982 18.71875,18.71875 C 22.428945,15.008505 22.428107,8.990658 18.71875,5.28125 C 16.86613,3.4286052 14.43323,2.4997462 12,2.5 z " />
+       style="opacity:0.4;fill:url(#linearGradient2231);fill-opacity:1;stroke:white;stroke-width:0.99999809;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 11.5,1.5 C 8.9408673,1.500267 6.3904601,2.4845389 4.4375,4.4375 C 0.53092837,8.3440732 0.53180564,14.656804 4.4375,18.5625 C 8.3431938,22.468195 14.655929,22.469073 18.5625,18.5625 C 22.469072,14.655927 22.468194,8.3431958 18.5625,4.4375 C 16.609962,2.4849619 14.058743,1.4997331 11.5,1.5 z "
+       id="path2215" />
     <path
-       style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1.00000036;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 15.713272,5.1062978 L 12.00096,8.8186095 L 8.2886482,5.1062978 L 5.0182784,8.3766676 L 8.7305901,12.088979 L 5.1066667,15.712903 L 8.3770366,18.983273 L 12.00096,15.359349 L 15.602786,18.961176 L 18.873156,15.690806 L 15.27133,12.088979 L 18.983642,8.3766676 L 15.713272,5.1062978 z "
-       id="path2233" />
+       style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1.00000024;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 15.527292,4.7878577 C 15.153659,4.4142246 14.558496,4.4142246 14.184863,4.7878577 L 11.500003,7.4727164 L 8.7941693,4.7668822 C 8.4383282,4.4110411 7.849532,4.4110411 7.4936909,4.7668822 L 4.7668812,7.4936919 C 4.4110402,7.8495329 4.4110401,8.4383292 4.7668812,8.7941703 L 7.4727154,11.500004 L 4.7878567,14.184864 C 4.4142238,14.558497 4.4142236,15.15366 4.7878567,15.527293 L 7.4727154,18.212151 C 7.8463484,18.585784 8.4415118,18.585784 8.8151448,18.212151 L 11.500003,15.527293 L 14.205838,18.233126 C 14.561679,18.588967 15.150475,18.588967 15.506317,18.233126 L 18.233125,15.506318 C 18.588966,15.150476 18.588965,14.56168 18.233125,14.205839 L 15.527292,11.500004 L 18.21215,8.8151458 C 18.585783,8.4415126 18.585784,7.84635 18.21215,7.4727164 L 15.527292,4.7878577 z "
+       id="path3032" />
     <path
-       style="opacity:1;fill:url(#linearGradient2270);fill-opacity:1;stroke:#555753;stroke-width:1.00000036;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 15.713272,5.1062978 L 12.00096,8.8186095 L 8.2886482,5.1062978 L 5.0182784,8.3766676 L 8.7305901,12.088979 L 5.1066667,15.712903 L 8.3770366,18.983273 L 12.00096,15.359349 L 15.602786,18.961176 L 18.873156,15.690806 L 15.27133,12.088979 L 18.983642,8.3766676 L 15.713272,5.1062978 z "
-       id="rect2204" />
+       style="opacity:1;fill:url(#linearGradient3040);fill-opacity:1.0;stroke:#555753;stroke-width:1.00000024;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 15.527292,4.7878577 C 15.153659,4.4142246 14.558496,4.4142246 14.184863,4.7878577 L 11.500003,7.4727164 L 8.7941693,4.7668822 C 8.4383282,4.4110411 7.849532,4.4110411 7.4936909,4.7668822 L 4.7668812,7.4936919 C 4.4110402,7.8495329 4.4110401,8.4383292 4.7668812,8.7941703 L 7.4727154,11.500004 L 4.7878567,14.184864 C 4.4142238,14.558497 4.4142236,15.15366 4.7878567,15.527293 L 7.4727154,18.212151 C 7.8463484,18.585784 8.4415118,18.585784 8.8151448,18.212151 L 11.500003,15.527293 L 14.205838,18.233126 C 14.561679,18.588967 15.150475,18.588967 15.506317,18.233126 L 18.233125,15.506318 C 18.588966,15.150476 18.588965,14.56168 18.233125,14.205839 L 15.527292,11.500004 L 18.21215,8.8151458 C 18.585783,8.4415126 18.585784,7.84635 18.21215,7.4727164 L 15.527292,4.7878577 z "
+       id="rect3024" />
     <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-1.0009557"
-       inkscape:original="M 8.28125 5.09375 L 5.03125 8.375 L 8.71875 12.09375 L 5.09375 15.71875 L 8.375 18.96875 L 12 15.34375 L 15.59375 18.96875 L 18.875 15.6875 L 15.28125 12.09375 L 18.96875 8.375 L 15.71875 5.09375 L 12 8.8125 L 8.28125 5.09375 z "
-       xlink:href="#rect2204"
-       style="opacity:1;fill:none;fill-opacity:1;stroke:#e1e1e1;stroke-width:1.00000036;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path2268"
-       inkscape:href="#rect2204"
-       d="M 8.28125,6.53125 L 6.46875,8.375 L 9.4375,11.375 C 9.6319915,11.563548 9.7417695,11.822867 9.7417695,12.09375 C 9.7417695,12.364633 9.6319915,12.623952 9.4375,12.8125 L 6.53125,15.71875 L 8.375,17.53125 L 11.28125,14.625 C 11.469798,14.430508 11.729117,14.320731 12,14.320731 C 12.270883,14.320731 12.530202,14.430508 12.71875,14.625 L 15.59375,17.53125 L 17.4375,15.6875 L 14.5625,12.8125 C 14.368008,12.623952 14.258231,12.364633 14.258231,12.09375 C 14.258231,11.822867 14.368008,11.563548 14.5625,11.375 L 17.53125,8.375 L 15.71875,6.53125 L 12.71875,9.53125 C 12.530202,9.7257415 12.270883,9.8355195 12,9.8355195 C 11.729117,9.8355195 11.469798,9.7257415 11.28125,9.53125 L 8.28125,6.53125 z " />
+       style="fill:none;fill-opacity:1;stroke:white;stroke-width:1.00000024;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 8.15625,5.625 L 5.625,8.15625 L 8.21875,10.78125 C 8.6216689,11.187934 8.6216689,11.843316 8.21875,12.25 L 5.625,14.875 L 8.125,17.375 L 10.75,14.78125 C 11.156684,14.378331 11.812066,14.378331 12.21875,14.78125 L 14.84375,17.375 L 17.375,14.84375 L 14.78125,12.21875 C 14.378331,11.812066 14.378331,11.156684 14.78125,10.75 L 17.375,8.125 L 14.875,5.625 L 12.25,8.21875 C 11.843316,8.6216689 11.187934,8.6216689 10.78125,8.21875 L 8.15625,5.625 z "
+       id="path3050" />
   </g>
 </svg>
Binary file pidgin/pixmaps/status/32/available.png has changed
Binary file pidgin/pixmaps/status/32/away.png has changed
Binary file pidgin/pixmaps/status/32/busy.png has changed
Binary file pidgin/pixmaps/status/32/invisible.png has changed
Binary file pidgin/pixmaps/status/32/offline.png has changed
--- a/pidgin/pixmaps/status/32/scalable/available.svg	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/status/32/scalable/available.svg	Mon Jun 18 01:48:35 2007 +0000
@@ -7,19 +7,19 @@
    xmlns:svg="http://www.w3.org/2000/svg"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/s odipodi-0.dtd"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    width="32"
    height="32"
    id="svg2"
    sodipodi:version="0.32"
-   inkscape:version="0.43"
+   inkscape:version="0.44.1"
    version="1.0"
    inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/status/32/available32.png"
    inkscape:export-xdpi="90"
    inkscape:export-ydpi="90"
-   sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/status/32/scalable"
-   sodipodi:docname="available32.svg">
+   sodipodi:docbase="/home/hbons/Desktop/experiment/status/32/scalable"
+   sodipodi:docname="available.svg">
   <defs
      id="defs4">
     <linearGradient
@@ -76,15 +76,434 @@
        x2="17.890068"
        y2="36.574547"
        gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient3025"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="11.024895"
+       x2="10.623409"
+       y1="2.7991772"
+       x1="4.5264969"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3007"
+       xlink:href="#linearGradient2804"
+       inkscape:collect="always" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient3005"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2812">
+      <stop
+         style="stop-color:#2e3436;stop-opacity:1;"
+         offset="0"
+         id="stop2814" />
+      <stop
+         style="stop-color:#2e3436;stop-opacity:0;"
+         offset="1"
+         id="stop2816" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2804">
+      <stop
+         style="stop-color:white;stop-opacity:1;"
+         offset="0"
+         id="stop2806" />
+      <stop
+         style="stop-color:white;stop-opacity:0;"
+         offset="1"
+         id="stop2808" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2949"
+       gradientUnits="userSpaceOnUse"
+       x1="17.890068"
+       y1="8.0617304"
+       x2="17.890068"
+       y2="40.032413" />
+    <linearGradient
+       id="linearGradient2951">
+      <stop
+         style="stop-color:#73d216;stop-opacity:1;"
+         offset="0"
+         id="stop2953" />
+      <stop
+         style="stop-color:#5ca911;stop-opacity:1;"
+         offset="1"
+         id="stop2955" />
+    </linearGradient>
     <linearGradient
        inkscape:collect="always"
        xlink:href="#linearGradient2851"
-       id="linearGradient2857"
+       id="linearGradient2963"
        x1="6.878005"
        y1="11.789385"
        x2="12.233074"
        y2="27.77807"
        gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2804"
+       id="linearGradient2810"
+       x1="4.5264969"
+       y1="2.7991772"
+       x2="10.623409"
+       y2="11.024895"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient2818"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(3.018423,0.664359,-1.388844,4.257661,-0.134567,-26.02469)"
+       r="0.8078171"
+       fy="6.9473476"
+       fx="4.8470273"
+       cy="6.9473476"
+       cx="4.8470273"
+       id="radialGradient2904"
+       xlink:href="#linearGradient2898"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       id="linearGradient1955"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientTransform="matrix(0.914124,-3.896132e-15,-2.475021e-18,1.631747,2.671799,-12.00863)"
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient1953"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient1935">
+      <stop
+         id="stop1937"
+         offset="0"
+         style="stop-color:#73d216;stop-opacity:1;" />
+      <stop
+         id="stop1939"
+         offset="1"
+         style="stop-color:#5ca911;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       y2="40.032413"
+       x2="17.890068"
+       y1="8.0617304"
+       x1="17.890068"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2269"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="36.603138"
+       x2="24.240097"
+       y1="9.4211226"
+       x1="15.498499"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient4740"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient4738"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2898"
+       inkscape:collect="always">
+      <stop
+         id="stop2900"
+         offset="0"
+         style="stop-color:white;stop-opacity:1;" />
+      <stop
+         id="stop2902"
+         offset="1"
+         style="stop-color:white;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient1983"
+       gradientUnits="userSpaceOnUse"
+       x1="15.498499"
+       y1="9.4211226"
+       x2="24.240097"
+       y2="36.603138"
+       gradientTransform="matrix(1.004822,0,0,1.004822,-2.476351,-2.157242)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient1986"
+       gradientUnits="userSpaceOnUse"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807"
+       gradientTransform="matrix(1.076595,0,0,1.076595,-3.760351,-3.418494)" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2898"
+       id="radialGradient1990"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(3.018423,0.664359,-1.388844,4.257661,-0.134567,-26.02469)"
+       cx="4.8470273"
+       cy="6.9473476"
+       fx="4.8470273"
+       fy="6.9473476"
+       r="0.8078171" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient1992"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       y2="21.045444"
+       x2="15.602553"
+       y1="1.5657365"
+       x1="15.602553"
+       gradientTransform="matrix(0.705322,0,0,0.705327,8.71963,7.710084)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2073"
+       xlink:href="#linearGradient2239"
+       inkscape:collect="always" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2057"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3816"
+       id="radialGradient2032"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2239"
+       id="linearGradient2040"
+       x1="15.602553"
+       y1="1.5657365"
+       x2="15.522223"
+       y2="33.483475"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.999824,0,0,0.999281,2.209264e-4,5.644055e-4)" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1985"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="11.024895"
+       x2="10.623409"
+       y1="2.7991772"
+       x1="4.5264969"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2100"
+       xlink:href="#linearGradient2804"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2086"
+       gradientUnits="userSpaceOnUse"
+       x1="17.890068"
+       y1="8.0617304"
+       x2="17.890068"
+       y2="40.032413" />
+    <linearGradient
+       id="linearGradient2080">
+      <stop
+         style="stop-color:#73d216;stop-opacity:1;"
+         offset="0"
+         id="stop2082" />
+      <stop
+         style="stop-color:#5ca911;stop-opacity:1;"
+         offset="1"
+         id="stop2084" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient2072"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2804"
+       id="linearGradient2070"
+       x1="4.5264969"
+       y1="2.7991772"
+       x2="10.623409"
+       y2="11.024895"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient2068"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.493392,0,4.185903)"
+       r="5.7619157"
+       fy="5.3375292"
+       fx="10.99079"
+       cy="5.3375292"
+       cx="10.99079"
+       id="radialGradient5135"
+       xlink:href="#linearGradient5129"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2239"
+       inkscape:collect="always">
+      <stop
+         id="stop2241"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop2243"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+    </linearGradient>
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.842757,0,0,-0.35721,19.80716,14.19321)"
+       r="6.6449099"
+       fy="10.457643"
+       fx="10.748654"
+       cy="10.457643"
+       cx="10.748654"
+       id="radialGradient3156"
+       xlink:href="#linearGradient3150"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient3150"
+       inkscape:collect="always">
+      <stop
+         id="stop3152"
+         offset="0"
+         style="stop-color:#2e3436;stop-opacity:1;" />
+      <stop
+         id="stop3154"
+         offset="1"
+         style="stop-color:#2e3436;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient5129"
+       inkscape:collect="always">
+      <stop
+         id="stop5131"
+         offset="0"
+         style="stop-color:white;stop-opacity:1;" />
+      <stop
+         id="stop5133"
+         offset="1"
+         style="stop-color:white;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2126"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.466524,0,0,0.466525,38.65385,10.80199)"
+       x1="15.498499"
+       y1="9.4211226"
+       x2="24.240097"
+       y2="36.603138" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2239"
+       id="linearGradient2132"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.705322,0,0,0.705327,-58.76363,3.243275)"
+       x1="15.602553"
+       y1="1.5657365"
+       x2="15.602553"
+       y2="21.045444" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2146"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.466524,0,0,0.466525,38.65385,10.80199)"
+       x1="15.498499"
+       y1="9.4211226"
+       x2="24.240097"
+       y2="36.603138" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient2148"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
   </defs>
   <sodipodi:namedview
      id="base"
@@ -94,16 +513,16 @@
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
      inkscape:zoom="14.928527"
-     inkscape:cx="21.066059"
-     inkscape:cy="16.155598"
+     inkscape:cx="1.0834072"
+     inkscape:cy="19.47767"
      inkscape:document-units="px"
      inkscape:current-layer="layer1"
      showgrid="true"
      fill="#eeeeec"
-     inkscape:window-width="1268"
-     inkscape:window-height="968"
-     inkscape:window-x="6"
-     inkscape:window-y="21" />
+     inkscape:window-width="1434"
+     inkscape:window-height="844"
+     inkscape:window-x="0"
+     inkscape:window-y="0" />
   <metadata
      id="metadata7">
     <rdf:RDF>
@@ -120,42 +539,22 @@
      inkscape:groupmode="layer"
      id="layer1">
     <path
-       d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1  22.45064,19.008621 A 8.6620579 8.6620579 0 1 1  39.774755 19.008621 z"
-       sodipodi:ry="8.6620579"
-       sodipodi:rx="8.6620579"
-       sodipodi:cy="19.008621"
-       sodipodi:cx="31.112698"
-       id="path4318"
-       style="opacity:1;color:black;fill:url(#radialGradient3822);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       sodipodi:type="arc"
-       transform="matrix(1.847136,0,0,0.865845,-41.46939,8.04148)" />
-    <path
+       transform="matrix(1.731691,0,0,0.461784,-37.88165,19.22212)"
        sodipodi:type="arc"
-       style="opacity:1;fill:url(#linearGradient2857);fill-opacity:1;fill-rule:evenodd;stroke:#418203;stroke-width:0.96092743;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path2245"
-       sodipodi:cx="17.890068"
-       sodipodi:cy="17.572527"
-       sodipodi:rx="13.932817"
-       sodipodi:ry="13.932817"
-       d="M 31.822886 17.572527 A 13.932817 13.932817 0 1 1  3.9572506,17.572527 A 13.932817 13.932817 0 1 1  31.822886 17.572527 z"
-       transform="matrix(1.040661,0,0,1.040661,-2.617502,-2.287049)" />
+       style="color:black;fill:url(#radialGradient2148);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       id="path2173"
+       sodipodi:cx="31.112698"
+       sodipodi:cy="19.008621"
+       sodipodi:rx="8.6620579"
+       sodipodi:ry="8.6620579"
+       d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1  22.45064,19.008621 A 8.6620579 8.6620579 0 1 1  39.774755 19.008621 z" />
     <path
-       sodipodi:type="arc"
-       style="opacity:0.5;fill:url(#linearGradient3155);fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.03206742;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path3145"
-       sodipodi:cx="17.890068"
-       sodipodi:cy="17.572527"
-       sodipodi:rx="13.932817"
-       sodipodi:ry="13.932817"
-       d="M 31.822886 17.572527 A 13.932817 13.932817 0 1 1  3.9572506,17.572527 A 13.932817 13.932817 0 1 1  31.822886 17.572527 z"
-       transform="matrix(0.968935,0,0,0.968925,-1.334307,-1.026606)" />
-    <image
-       id="image1323"
-       height="64.794617"
-       width="64.794617"
-       sodipodi:absref="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-       xlink:href="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
-       x="-74"
-       y="-17" />
+       style="fill:url(#linearGradient1986);fill-opacity:1;fill-rule:evenodd;stroke:#306300;stroke-width:0.99999946;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 30.500005,15.500002 C 30.500005,23.780003 23.780005,30.500004 15.500008,30.500004 C 7.2200097,30.500004 0.50001191,23.780003 0.50001191,15.500002 C 0.50001191,7.2200001 7.2200097,0.49999934 15.500008,0.49999934 C 23.780005,0.49999934 30.500005,7.2200001 30.500005,15.500002 z "
+       id="path4331" />
+    <path
+       style="opacity:0.6;fill:url(#linearGradient1983);fill-opacity:1;fill-rule:evenodd;stroke:white;stroke-width:0.99999863;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 29.499996,15.5 C 29.499996,23.227999 23.227996,29.500002 15.499996,29.500002 C 7.7719974,29.500002 1.4999949,23.227999 1.4999949,15.5 C 1.4999949,7.7719992 7.7719974,1.4999993 15.499996,1.4999993 C 23.227996,1.4999993 29.499996,7.7719992 29.499996,15.5 z "
+       id="path4333" />
   </g>
 </svg>
--- a/pidgin/pixmaps/status/32/scalable/away.svg	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/status/32/scalable/away.svg	Mon Jun 18 01:48:35 2007 +0000
@@ -7,23 +7,47 @@
    xmlns:svg="http://www.w3.org/2000/svg"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/s odipodi-0.dtd"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    width="32"
    height="32"
    id="svg1331"
    sodipodi:version="0.32"
-   inkscape:version="0.43"
+   inkscape:version="0.44.1"
    version="1.0"
-   inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/status/32/away32.png"
+   inkscape:export-filename="/home/hbons/GUI/Tango/Gaim Refresh/status/22/away.png"
    inkscape:export-xdpi="90"
    inkscape:export-ydpi="90"
-   sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/status/32/scalable"
-   sodipodi:docname="away32.svg">
+   sodipodi:docbase="/home/hbons/Desktop/experiment/status/32/scalable"
+   sodipodi:docname="away.svg">
   <defs
      id="defs1333">
     <linearGradient
        inkscape:collect="always"
+       id="linearGradient2808">
+      <stop
+         style="stop-color:white;stop-opacity:1;"
+         offset="0"
+         id="stop2810" />
+      <stop
+         style="stop-color:white;stop-opacity:0;"
+         offset="1"
+         id="stop2812" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient5129">
+      <stop
+         style="stop-color:white;stop-opacity:1;"
+         offset="0"
+         id="stop5131" />
+      <stop
+         style="stop-color:white;stop-opacity:0;"
+         offset="1"
+         id="stop5133" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
        id="linearGradient3816">
       <stop
          style="stop-color:#000000;stop-opacity:1;"
@@ -34,15 +58,28 @@
          offset="1"
          id="stop3820" />
     </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3150">
+      <stop
+         style="stop-color:#2e3436;stop-opacity:1;"
+         offset="0"
+         id="stop3152" />
+      <stop
+         style="stop-color:#2e3436;stop-opacity:0;"
+         offset="1"
+         id="stop3154" />
+    </linearGradient>
     <radialGradient
        inkscape:collect="always"
-       xlink:href="#linearGradient3816"
-       id="radialGradient3822"
-       cx="31.112698"
-       cy="19.008621"
-       fx="31.112698"
-       fy="19.008621"
-       r="8.6620579"
+       xlink:href="#linearGradient3150"
+       id="radialGradient3156"
+       cx="10.748654"
+       cy="10.457643"
+       fx="10.748654"
+       fy="10.457643"
+       r="6.6449099"
+       gradientTransform="matrix(-0.842757,0,0,-0.35721,19.80716,14.19321)"
        gradientUnits="userSpaceOnUse" />
     <linearGradient
        inkscape:collect="always"
@@ -56,16 +93,171 @@
          offset="1"
          id="stop2243" />
     </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5129"
+       id="radialGradient5135"
+       cx="10.99079"
+       cy="5.3375292"
+       fx="10.99079"
+       fy="5.3375292"
+       r="5.7619157"
+       gradientTransform="matrix(1,0,0,0.493392,0,4.185903)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient2818"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="11.024895"
+       x2="10.623409"
+       y1="2.7991772"
+       x1="4.5264969"
+       id="linearGradient2810"
+       xlink:href="#linearGradient2804"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       id="linearGradient2857"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient3149"
+       inkscape:collect="always">
+      <stop
+         id="stop3151"
+         offset="0"
+         style="stop-color:#eeeeec;stop-opacity:1;" />
+      <stop
+         id="stop3153"
+         offset="1"
+         style="stop-color:#eeeeec;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2851">
+      <stop
+         id="stop2853"
+         offset="0"
+         style="stop-color:#73d216;stop-opacity:1;" />
+      <stop
+         id="stop2855"
+         offset="1"
+         style="stop-color:#5ca911;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       y2="40.032413"
+       x2="17.890068"
+       y1="8.0617304"
+       x1="17.890068"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2269"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2804"
+       inkscape:collect="always">
+      <stop
+         id="stop2806"
+         offset="0"
+         style="stop-color:white;stop-opacity:1;" />
+      <stop
+         id="stop2808"
+         offset="1"
+         style="stop-color:white;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2812"
+       inkscape:collect="always">
+      <stop
+         id="stop2814"
+         offset="0"
+         style="stop-color:#2e3436;stop-opacity:1;" />
+      <stop
+         id="stop2816"
+         offset="1"
+         style="stop-color:#2e3436;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2804"
+       id="linearGradient1983"
+       gradientUnits="userSpaceOnUse"
+       x1="4.5264969"
+       y1="2.7991772"
+       x2="10.623409"
+       y2="11.024895" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient1985"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       gradientTransform="matrix(0.999824,0,0,0.999281,2.209264e-4,5.644055e-4)"
+       gradientUnits="userSpaceOnUse"
+       y2="33.483475"
+       x2="15.522223"
+       y1="1.5657365"
+       x1="15.602553"
+       id="linearGradient2040"
+       xlink:href="#linearGradient2239"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient2032"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3816"
+       id="radialGradient2057"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
     <linearGradient
        inkscape:collect="always"
        xlink:href="#linearGradient2239"
-       id="linearGradient2245"
+       id="linearGradient2073"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.705322,0,0,0.705327,8.71963,7.710084)"
        x1="15.602553"
        y1="1.5657365"
-       x2="15.522223"
-       y2="33.483475"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.999824,0,0,0.999281,2.209264e-4,5.644055e-4)" />
+       x2="15.602553"
+       y2="21.045444" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2808"
+       id="radialGradient2814"
+       cx="5.2511673"
+       cy="7.3335675"
+       fx="5.2511673"
+       fy="7.3335675"
+       r="0.82651663"
+       gradientTransform="matrix(1,0,0,1.337946,0,-2.478349)"
+       gradientUnits="userSpaceOnUse" />
   </defs>
   <sodipodi:namedview
      id="base"
@@ -74,20 +266,20 @@
      borderopacity="1.0"
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
-     inkscape:zoom="19.69831"
-     inkscape:cx="23.600016"
-     inkscape:cy="15.388506"
+     inkscape:zoom="13.928809"
+     inkscape:cx="28.28763"
+     inkscape:cy="14.998178"
      inkscape:current-layer="layer1"
      showgrid="true"
      inkscape:grid-bbox="true"
      inkscape:document-units="px"
      fill="#729fcf"
-     inkscape:window-width="1268"
-     inkscape:window-height="972"
-     inkscape:window-x="6"
-     inkscape:window-y="21"
-     showguides="true"
-     inkscape:guide-bbox="true" />
+     inkscape:window-width="1434"
+     inkscape:window-height="844"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     width="32px"
+     height="32px" />
   <metadata
      id="metadata1336">
     <rdf:RDF>
@@ -109,63 +301,101 @@
        sodipodi:rx="8.6620579"
        sodipodi:cy="19.008621"
        sodipodi:cx="31.112698"
-       id="path4318"
-       style="opacity:1;color:#000000;fill:url(#radialGradient3822);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       id="path1948"
+       style="color:black;fill:url(#radialGradient1985);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
        sodipodi:type="arc"
-       transform="matrix(1.847136,0,0,0.865845,-41.46939,8.04148)" />
+       transform="matrix(1.731691,0,0,0.461784,-37.87757,19.22211)" />
     <path
        sodipodi:type="arc"
-       style="opacity:1;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:evenodd;stroke:#204a87;stroke-width:0.98932087px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       id="path1339"
+       style="color:black;fill:#729fcf;fill-opacity:1;fill-rule:evenodd;stroke:#173867;stroke-width:0.95645106px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       id="path1951"
        sodipodi:cx="15.590227"
        sodipodi:cy="16.57217"
        sodipodi:rx="14.345175"
        sodipodi:ry="14.345175"
        d="M 29.935402 16.57217 A 14.345175 14.345175 0 1 1  1.2450523,16.57217 A 14.345175 14.345175 0 1 1  29.935402 16.57217 z"
-       transform="matrix(1.010793,0,0,1.010792,0.241509,-0.751017)" />
+       transform="matrix(1.045505,0,0,1.045554,-0.797598,-1.825749)" />
     <path
        sodipodi:type="arc"
-       style="opacity:1;color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#204a87;stroke-width:1.24782109px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       id="path1341"
+       style="fill:#8ab0d7;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="path2788"
+       sodipodi:cx="-3.8088531"
+       sodipodi:cy="3.303823"
+       sodipodi:rx="3.1932809"
+       sodipodi:ry="3.3471739"
+       d="M -0.61557221 3.303823 A 3.1932809 3.3471739 0 1 1  -7.0021341,3.303823 A 3.1932809 3.3471739 0 1 1  -0.61557221 3.303823 z"
+       transform="matrix(4.414832,0,0,4.210029,32.44953,1.716868)" />
+    <path
+       sodipodi:type="arc"
+       style="opacity:0.40340911;color:black;fill:#babdb6;fill-opacity:1;fill-rule:evenodd;stroke:#173867;stroke-width:1.19542968px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       id="path1954"
        sodipodi:cx="15.590227"
        sodipodi:cy="16.57217"
        sodipodi:rx="14.345175"
        sodipodi:ry="14.345175"
        d="M 29.935402 16.57217 A 14.345175 14.345175 0 1 1  1.2450523,16.57217 A 14.345175 14.345175 0 1 1  29.935402 16.57217 z"
-       transform="matrix(0.80139,0,0,0.801405,3.511281,2.723938)" />
+       transform="matrix(0.836518,0,0,0.836518,2.458491,1.637077)" />
+    <path
+       sodipodi:type="arc"
+       style="fill:#dcdcd8;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="path2796"
+       sodipodi:cx="6.0403023"
+       sodipodi:cy="7.5551186"
+       sodipodi:rx="1.615877"
+       sodipodi:ry="1.3273276"
+       d="M 7.6561793 7.5551186 A 1.615877 1.3273276 0 1 1  4.4244252,7.5551186 A 1.615877 1.3273276 0 1 1  7.6561793 7.5551186 z"
+       transform="matrix(7.116878,0,0,8.664024,-27.4881,-49.95773)" />
     <path
        sodipodi:type="arc"
-       style="opacity:1;color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#2e3436;stroke-width:5.84032869px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       id="path2216"
+       style="opacity:0.76704544;fill:none;fill-opacity:1;stroke:url(#linearGradient1983);stroke-width:0.37457478;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="path2802"
+       sodipodi:cx="7.5"
+       sodipodi:cy="7"
+       sodipodi:rx="5.5"
+       sodipodi:ry="5"
+       d="M 13 7 A 5.5 5 0 1 1  2,7 A 5.5 5 0 1 1  13 7 z"
+       transform="matrix(2.545454,0,0,2.8,-3.590908,-4.100001)" />
+    <path
+       sodipodi:type="arc"
+       style="fill:url(#radialGradient2814);fill-opacity:1.0;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="path2852"
+       sodipodi:cx="6.0403023"
+       sodipodi:cy="7.5551186"
+       sodipodi:rx="1.615877"
+       sodipodi:ry="1.3273276"
+       d="M 4.835244,8.4394021 A 1.615877,1.3273276 0 0 1 6.0776839,6.2281462 L 6.0403023,7.5551186 z"
+       transform="matrix(5.732654,0,0,7.234355,-19.36499,-39.05363)"
+       sodipodi:start="2.4124729"
+       sodipodi:end="4.735525" />
+    <path
+       sodipodi:type="arc"
+       style="color:black;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#2e3436;stroke-width:7.17263222px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       id="path2051"
        sodipodi:cx="15.590227"
        sodipodi:cy="16.57217"
        sodipodi:rx="14.345175"
        sodipodi:ry="14.345175"
        d="M 29.935402 16.57217 A 14.345175 14.345175 0 1 1  1.2450523,16.57217 A 14.345175 14.345175 0 1 1  29.935402 16.57217 z"
-       transform="matrix(0.171225,0,0,0.171225,13.33055,13.16244)" />
-    <path
-       style="opacity:0.5;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient2245);stroke-width:0.99999946px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       d="M 29.484663,15.989048 C 29.484663,23.430003 23.442356,29.46904 15.997368,29.46904 C 8.5523815,29.46904 2.5100737,23.430003 2.5100737,15.989048 C 2.5100737,8.5480941 8.5523815,2.5090586 15.997368,2.5090586 C 23.442356,2.5090586 29.484663,8.5480941 29.484663,15.989048 z "
-       id="path2220" />
-    <path
-       sodipodi:type="arc"
-       style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path1342"
-       sodipodi:cx="19.747887"
-       sodipodi:cy="9.4599953"
-       sodipodi:rx="1.4722075"
-       sodipodi:ry="2.6398203"
-       d="M 21.220094 9.4599953 A 1.4722075 2.6398203 0 1 1  18.275679,9.4599953 A 1.4722075 2.6398203 0 1 1  21.220094 9.4599953 z"
-       transform="matrix(0.882374,0.509439,-0.56822,0.984187,6.966287,-8.07548)" />
-    <path
-       sodipodi:type="arc"
-       style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path1344"
-       sodipodi:cx="19.747887"
-       sodipodi:cy="9.4599953"
-       sodipodi:rx="1.4722075"
-       sodipodi:ry="2.6398203"
-       d="M 21.220094 9.4599953 A 1.4722075 2.6398203 0 1 1  18.275679,9.4599953 A 1.4722075 2.6398203 0 1 1  21.220094 9.4599953 z"
-       transform="matrix(0.882374,-0.509439,-0.56822,-0.984187,6.966287,40.07548)" />
+       transform="matrix(0.13942,0,0,0.139419,13.32641,13.18954)" />
+    <rect
+       style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:4.86999989;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect4234"
+       width="2.0651035"
+       height="6.1953154"
+       x="20.887754"
+       y="-8.7545109"
+       transform="matrix(0.707107,0.707107,-0.707107,0.707107,0,0)"
+       rx="1.0325518"
+       ry="1.0027943" />
+    <rect
+       style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:4.86999989;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2080"
+       width="2.065105"
+       height="6.1953192"
+       x="-1.0325458"
+       y="-30.674829"
+       transform="matrix(0.707107,-0.707107,-0.707107,-0.707107,0,0)"
+       rx="1.0325525"
+       ry="1.002795" />
   </g>
 </svg>
--- a/pidgin/pixmaps/status/32/scalable/busy.svg	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/status/32/scalable/busy.svg	Mon Jun 18 01:48:35 2007 +0000
@@ -7,19 +7,19 @@
    xmlns:svg="http://www.w3.org/2000/svg"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/s odipodi-0.dtd"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    width="32"
    height="32"
    id="svg1331"
    sodipodi:version="0.32"
-   inkscape:version="0.43"
+   inkscape:version="0.44.1"
    version="1.0"
    inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/status/32/busy32.png"
    inkscape:export-xdpi="90"
    inkscape:export-ydpi="90"
-   sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/status/32/scalable"
-   sodipodi:docname="busy32.svg">
+   sodipodi:docbase="/home/hbons/Desktop/experiment/32/scalable"
+   sodipodi:docname="busy.svg">
   <defs
      id="defs1333">
     <linearGradient
@@ -34,16 +34,6 @@
          offset="1"
          id="stop3820" />
     </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3816"
-       id="radialGradient3822"
-       cx="31.112698"
-       cy="19.008621"
-       fx="31.112698"
-       fy="19.008621"
-       r="8.6620579"
-       gradientUnits="userSpaceOnUse" />
     <linearGradient
        inkscape:collect="always"
        id="linearGradient2186">
@@ -68,26 +58,554 @@
          offset="1"
          id="stop2243" />
     </linearGradient>
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2148"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="36.603138"
+       x2="24.240097"
+       y1="9.4211226"
+       x1="15.498499"
+       gradientTransform="matrix(0.466524,0,0,0.466525,38.65385,10.80199)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2146"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="21.045444"
+       x2="15.602553"
+       y1="1.5657365"
+       x1="15.602553"
+       gradientTransform="matrix(0.705322,0,0,0.705327,-58.76363,3.243275)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2132"
+       xlink:href="#linearGradient2239"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="36.603138"
+       x2="24.240097"
+       y1="9.4211226"
+       x1="15.498499"
+       gradientTransform="matrix(0.466524,0,0,0.466525,38.65385,10.80199)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2126"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient5129">
+      <stop
+         style="stop-color:white;stop-opacity:1;"
+         offset="0"
+         id="stop5131" />
+      <stop
+         style="stop-color:white;stop-opacity:0;"
+         offset="1"
+         id="stop5133" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3150">
+      <stop
+         style="stop-color:#2e3436;stop-opacity:1;"
+         offset="0"
+         id="stop3152" />
+      <stop
+         style="stop-color:#2e3436;stop-opacity:0;"
+         offset="1"
+         id="stop3154" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3150"
+       id="radialGradient3156"
+       cx="10.748654"
+       cy="10.457643"
+       fx="10.748654"
+       fy="10.457643"
+       r="6.6449099"
+       gradientTransform="matrix(-0.842757,0,0,-0.35721,19.80716,14.19321)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5129"
+       id="radialGradient5135"
+       cx="10.99079"
+       cy="5.3375292"
+       fx="10.99079"
+       fy="5.3375292"
+       r="5.7619157"
+       gradientTransform="matrix(1,0,0,0.493392,0,4.185903)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient2068"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="11.024895"
+       x2="10.623409"
+       y1="2.7991772"
+       x1="4.5264969"
+       id="linearGradient2070"
+       xlink:href="#linearGradient2804"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       id="linearGradient2072"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2080">
+      <stop
+         id="stop2082"
+         offset="0"
+         style="stop-color:#73d216;stop-opacity:1;" />
+      <stop
+         id="stop2084"
+         offset="1"
+         style="stop-color:#5ca911;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       y2="40.032413"
+       x2="17.890068"
+       y1="8.0617304"
+       x1="17.890068"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2086"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2804"
+       id="linearGradient2100"
+       gradientUnits="userSpaceOnUse"
+       x1="4.5264969"
+       y1="2.7991772"
+       x2="10.623409"
+       y2="11.024895" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient1985"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       gradientTransform="matrix(0.999824,0,0,0.999281,2.209264e-4,5.644055e-4)"
+       gradientUnits="userSpaceOnUse"
+       y2="33.483475"
+       x2="15.522223"
+       y1="1.5657365"
+       x1="15.602553"
+       id="linearGradient2040"
+       xlink:href="#linearGradient2239"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient2032"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3816"
+       id="radialGradient2057"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
     <linearGradient
        inkscape:collect="always"
        xlink:href="#linearGradient2239"
-       id="linearGradient2245"
-       x1="15.535398"
-       y1="1.8014067"
-       x2="15.535398"
-       y2="48.674999"
+       id="linearGradient2073"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.705322,0,0,0.705327,8.71963,7.710084)"
+       x1="15.602553"
+       y1="1.5657365"
+       x2="15.602553"
+       y2="21.045444" />
+    <radialGradient
+       r="0.8078171"
+       fy="6.9473476"
+       fx="4.8470273"
+       cy="6.9473476"
+       cx="4.8470273"
+       gradientTransform="matrix(3.018423,0.664359,-1.388844,4.257661,-0.134567,-26.02469)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1990"
+       xlink:href="#linearGradient2898"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2898">
+      <stop
+         style="stop-color:white;stop-opacity:1;"
+         offset="0"
+         id="stop2900" />
+      <stop
+         style="stop-color:white;stop-opacity:0;"
+         offset="1"
+         id="stop2902" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient4738"
+       gradientUnits="userSpaceOnUse"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient4740"
+       gradientUnits="userSpaceOnUse"
+       x1="15.498499"
+       y1="9.4211226"
+       x2="24.240097"
+       y2="36.603138" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2269"
+       gradientUnits="userSpaceOnUse"
+       x1="17.890068"
+       y1="8.0617304"
+       x2="17.890068"
+       y2="40.032413" />
+    <linearGradient
+       id="linearGradient1935">
+      <stop
+         style="stop-color:#73d216;stop-opacity:1;"
+         offset="0"
+         id="stop1937" />
+      <stop
+         style="stop-color:#5ca911;stop-opacity:1;"
+         offset="1"
+         id="stop1939" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3816"
+       id="radialGradient1953"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.914124,-3.896132e-15,-2.475021e-18,1.631747,2.671799,-12.00863)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient1955"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient2818"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="11.024895"
+       x2="10.623409"
+       y1="2.7991772"
+       x1="4.5264969"
+       id="linearGradient2810"
+       xlink:href="#linearGradient2804"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       id="linearGradient2963"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2951">
+      <stop
+         id="stop2953"
+         offset="0"
+         style="stop-color:#73d216;stop-opacity:1;" />
+      <stop
+         id="stop2955"
+         offset="1"
+         style="stop-color:#5ca911;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       y2="40.032413"
+       x2="17.890068"
+       y1="8.0617304"
+       x1="17.890068"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2949"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2804"
+       inkscape:collect="always">
+      <stop
+         id="stop2806"
+         offset="0"
+         style="stop-color:white;stop-opacity:1;" />
+      <stop
+         id="stop2808"
+         offset="1"
+         style="stop-color:white;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2812"
+       inkscape:collect="always">
+      <stop
+         id="stop2814"
+         offset="0"
+         style="stop-color:#2e3436;stop-opacity:1;" />
+      <stop
+         id="stop2816"
+         offset="1"
+         style="stop-color:#2e3436;stop-opacity:0;" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient3005"
        gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1.000376,0,0,0.999343,-1.147524e-3,1.523185e-2)" />
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2804"
+       id="linearGradient3007"
+       gradientUnits="userSpaceOnUse"
+       x1="4.5264969"
+       y1="2.7991772"
+       x2="10.623409"
+       y2="11.024895" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="36.574547"
+       x2="17.890068"
+       y1="8.3091545"
+       x1="17.890068"
+       id="linearGradient3155"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient1988"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient3149"
+       inkscape:collect="always">
+      <stop
+         id="stop3151"
+         offset="0"
+         style="stop-color:#eeeeec;stop-opacity:1;" />
+      <stop
+         id="stop3153"
+         offset="1"
+         style="stop-color:#eeeeec;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2851">
+      <stop
+         id="stop2853"
+         offset="0"
+         style="stop-color:#73d216;stop-opacity:1;" />
+      <stop
+         id="stop2855"
+         offset="1"
+         style="stop-color:#5ca911;stop-opacity:1;" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient2070"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2083"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.004822,0,0,1.004822,-54.47635,15.84276)"
+       x1="15.498499"
+       y1="9.4211226"
+       x2="24.240097"
+       y2="36.603138" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient2087"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.076595,0,0,1.076595,-55.76035,14.58151)"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient2093"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       id="linearGradient2857"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientTransform="matrix(0.914124,-3.896132e-15,-2.475021e-18,1.631747,2.671799,-12.00863)"
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient2187"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2169">
+      <stop
+         id="stop2171"
+         offset="0"
+         style="stop-color:#73d216;stop-opacity:1;" />
+      <stop
+         id="stop2173"
+         offset="1"
+         style="stop-color:#5ca911;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       y2="40.032413"
+       x2="17.890068"
+       y1="8.0617304"
+       x1="17.890068"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2167"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(0.482882,0,0,0.482874,0.269812,0.26982)"
+       gradientUnits="userSpaceOnUse"
+       y2="39.834526"
+       x2="31.18539"
+       y1="4.5934086"
+       x1="8.7505674"
+       id="linearGradient2165"
+       xlink:href="#linearGradient2239"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(0.684526,0,0,0.687171,-0.20455,-0.253325)"
+       gradientUnits="userSpaceOnUse"
+       y2="17.697369"
+       x2="11.226587"
+       y1="-1.5641226"
+       x1="9.2594385"
+       id="linearGradient2157"
+       xlink:href="#linearGradient2186"
+       inkscape:collect="always" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2149"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(3.018423,0.664359,-1.388844,4.257661,-0.134567,-26.02469)"
+       r="0.8078171"
+       fy="6.9473476"
+       fx="4.8470273"
+       cy="6.9473476"
+       cx="4.8470273"
+       id="radialGradient2141"
+       xlink:href="#linearGradient2898"
+       inkscape:collect="always" />
     <linearGradient
        inkscape:collect="always"
        xlink:href="#linearGradient2186"
-       id="linearGradient2194"
-       x1="11.226587"
-       y1="-5.4832759"
-       x2="11.226587"
-       y2="17.697369"
+       id="linearGradient2208"
        gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(1.418323,0,0,1.416852,-1.021803,-0.99085)" />
+       gradientTransform="matrix(3.048768,0,0,3.033857,-3.920843,-3.729339)"
+       x1="3.3119085"
+       y1="-0.76356995"
+       x2="9.0812168"
+       y2="10.792614" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2239"
+       id="linearGradient2210"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.150367,0,0,2.139859,-1.726897,-1.575055)"
+       x1="6.6158633"
+       y1="4.5275822"
+       x2="11.507221"
+       y2="32.896225" />
   </defs>
   <sodipodi:namedview
      id="base"
@@ -96,18 +614,18 @@
      borderopacity="1.0"
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
-     inkscape:zoom="25.992076"
-     inkscape:cx="23.061682"
-     inkscape:cy="14.291409"
+     inkscape:zoom="11.313708"
+     inkscape:cx="32.077294"
+     inkscape:cy="17.208225"
      inkscape:current-layer="layer1"
      showgrid="true"
      inkscape:grid-bbox="true"
      inkscape:document-units="px"
      fill="#ef2929"
-     inkscape:window-width="1268"
-     inkscape:window-height="972"
-     inkscape:window-x="6"
-     inkscape:window-y="21" />
+     inkscape:window-width="1440"
+     inkscape:window-height="849"
+     inkscape:window-x="0"
+     inkscape:window-y="0" />
   <metadata
      id="metadata1336">
     <rdf:RDF>
@@ -124,43 +642,47 @@
      inkscape:label="Layer 1"
      inkscape:groupmode="layer">
     <path
-       d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1  22.45064,19.008621 A 8.6620579 8.6620579 0 1 1  39.774755 19.008621 z"
-       sodipodi:ry="8.6620579"
-       sodipodi:rx="8.6620579"
-       sodipodi:cy="19.008621"
+       transform="matrix(1.731691,0,0,0.461784,-37.87759,19.22212)"
+       sodipodi:type="arc"
+       style="color:black;fill:url(#radialGradient2093);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       id="path2091"
        sodipodi:cx="31.112698"
-       id="path4318"
-       style="opacity:1;color:#000000;fill:url(#radialGradient3822);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       sodipodi:type="arc"
-       transform="matrix(1.847136,0,0,0.865845,-41.46938,8.041481)" />
+       sodipodi:cy="19.008621"
+       sodipodi:rx="8.6620579"
+       sodipodi:ry="8.6620579"
+       d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1  22.45064,19.008621 A 8.6620579 8.6620579 0 1 1  39.774755 19.008621 z" />
     <path
        sodipodi:type="arc"
-       style="opacity:1;color:#000000;fill:#ef2929;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.36561811px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       id="path1311"
+       style="color:black;fill:#ef2929;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.36561811px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       id="path2194"
        sodipodi:cx="15.590227"
        sodipodi:cy="16.57217"
        sodipodi:rx="14.345175"
        sodipodi:ry="14.345175"
        d="M 29.935402 16.57217 A 14.345175 14.345175 0 1 1  1.2450523,16.57217 A 14.345175 14.345175 0 1 1  29.935402 16.57217 z"
-       transform="matrix(0.989705,0,0,0.989705,0.437593,-0.53424)" />
+       transform="matrix(0.936036,0,0,0.936032,1.023071,0.100614)" />
     <path
        sodipodi:type="arc"
-       style="opacity:1;color:#000000;fill:#ef2929;fill-opacity:1;fill-rule:evenodd;stroke:#a40000;stroke-width:0.98950732px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       id="path1339"
+       style="color:black;fill:#f24747;fill-opacity:1;fill-rule:evenodd;stroke:#820000;stroke-width:0.95634508px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       id="path2196"
        sodipodi:cx="15.590227"
        sodipodi:cy="16.57217"
        sodipodi:rx="14.345175"
        sodipodi:ry="14.345175"
        d="M 29.935402 16.57217 A 14.345175 14.345175 0 1 1  1.2450523,16.57217 A 14.345175 14.345175 0 1 1  29.935402 16.57217 z"
-       transform="matrix(1.010428,0,0,1.010778,0.242013,-0.750701)" />
+       transform="matrix(1.045648,0,0,1.045648,-0.801887,-1.828653)" />
     <path
-       style="opacity:0.6;color:#000000;fill:url(#linearGradient2194);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient2245);stroke-width:1.0000006px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       d="M 29.499568,16.004716 C 29.499568,23.446135 23.453927,29.485548 16.004828,29.485548 C 8.5557329,29.485548 2.5100898,23.446135 2.5100898,16.004716 C 2.5100898,8.5632961 8.5557329,2.5238833 16.004828,2.5238833 C 23.453927,2.5238833 29.499568,8.5632961 29.499568,16.004716 z "
-       id="path2220" />
-    <path
-       style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#a40000;stroke-width:0.99999958px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       d="M 27.51954,15.864482 C 27.51954,20.204712 25.510558,19.437434 15.893137,19.437434 C 6.2213077,19.437434 4.46153,20.133953 4.46153,16.055453 C 4.46153,11.913293 6.4064326,12.529223 15.990534,12.529223 C 25.520227,12.529223 27.51954,11.460602 27.51954,15.864482 z "
-       id="path1341"
-       sodipodi:nodetypes="czzzz" />
+       style="opacity:0.6;color:black;fill:url(#linearGradient2208);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient2210);stroke-width:0.99999946px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       d="M 29.499988,15.499986 C 29.499988,23.227979 23.227989,29.499978 15.49999,29.499978 C 7.7719953,29.499978 1.4999991,23.227979 1.4999991,15.499986 C 1.4999991,7.7719948 7.7719953,1.4999985 15.49999,1.4999985 C 23.227989,1.4999985 29.499988,7.7719948 29.499988,15.499986 z "
+       id="path2199" />
+    <rect
+       style="fill:#eeeeec;fill-opacity:1;stroke:#a40000;stroke-width:1.00000036;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect3207"
+       width="24"
+       height="5.9877748"
+       x="3.5000014"
+       y="12.535524"
+       rx="2.098541"
+       ry="1.919746" />
   </g>
 </svg>
--- a/pidgin/pixmaps/status/32/scalable/offline.svg	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/status/32/scalable/offline.svg	Mon Jun 18 01:48:35 2007 +0000
@@ -15,7 +15,7 @@
    sodipodi:version="0.32"
    inkscape:version="0.44.1"
    version="1.0"
-   sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/status/32/scalable"
+   sodipodi:docbase="/home/hbons/Desktop/experiment/status/32/scalable"
    sodipodi:docname="offline.svg"
    inkscape:export-filename="/home/hbons/GUI/Tango/Gaim Refresh/status/32/offline.png"
    inkscape:export-xdpi="90"
@@ -106,10 +106,498 @@
        id="linearGradient2270"
        gradientUnits="userSpaceOnUse"
        x1="12.00096"
-       y1="18.000015"
+       y1="17.203793"
        x2="12.00096"
-       y2="12.421011"
-       gradientTransform="matrix(1.318182,0,0,1.318182,-2.3895e-2,0.33147)" />
+       y2="9.1482677"
+       gradientTransform="matrix(1.40375,0,0,1.403934,-1.668488,-1.296374)" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2148"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="36.603138"
+       x2="24.240097"
+       y1="9.4211226"
+       x1="15.498499"
+       gradientTransform="matrix(0.466524,0,0,0.466525,38.65385,10.80199)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2146"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="21.045444"
+       x2="15.602553"
+       y1="1.5657365"
+       x1="15.602553"
+       gradientTransform="matrix(0.705322,0,0,0.705327,-58.76363,3.243275)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2132"
+       xlink:href="#linearGradient2239"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="36.603138"
+       x2="24.240097"
+       y1="9.4211226"
+       x1="15.498499"
+       gradientTransform="matrix(0.466524,0,0,0.466525,38.65385,10.80199)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2126"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient5129">
+      <stop
+         style="stop-color:white;stop-opacity:1;"
+         offset="0"
+         id="stop5131" />
+      <stop
+         style="stop-color:white;stop-opacity:0;"
+         offset="1"
+         id="stop5133" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3150"
+       id="radialGradient2035"
+       cx="10.748654"
+       cy="10.457643"
+       fx="10.748654"
+       fy="10.457643"
+       r="6.6449099"
+       gradientTransform="matrix(-0.842757,0,0,-0.35721,19.80716,14.19321)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2239">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop2241" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop2243" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5129"
+       id="radialGradient5135"
+       cx="10.99079"
+       cy="5.3375292"
+       fx="10.99079"
+       fy="5.3375292"
+       r="5.7619157"
+       gradientTransform="matrix(1,0,0,0.493392,0,4.185903)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient2068"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="11.024895"
+       x2="10.623409"
+       y1="2.7991772"
+       x1="4.5264969"
+       id="linearGradient2070"
+       xlink:href="#linearGradient2804"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       id="linearGradient2072"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2080">
+      <stop
+         id="stop2082"
+         offset="0"
+         style="stop-color:#73d216;stop-opacity:1;" />
+      <stop
+         id="stop2084"
+         offset="1"
+         style="stop-color:#5ca911;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       y2="40.032413"
+       x2="17.890068"
+       y1="8.0617304"
+       x1="17.890068"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2086"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2804"
+       id="linearGradient2100"
+       gradientUnits="userSpaceOnUse"
+       x1="4.5264969"
+       y1="2.7991772"
+       x2="10.623409"
+       y2="11.024895" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient1985"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       gradientTransform="matrix(0.999824,0,0,0.999281,2.209264e-4,5.644055e-4)"
+       gradientUnits="userSpaceOnUse"
+       y2="33.483475"
+       x2="15.522223"
+       y1="1.5657365"
+       x1="15.602553"
+       id="linearGradient2040"
+       xlink:href="#linearGradient2239"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient2032"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3816"
+       id="radialGradient2057"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2239"
+       id="linearGradient2073"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.705322,0,0,0.705327,8.71963,7.710084)"
+       x1="15.602553"
+       y1="1.5657365"
+       x2="15.602553"
+       y2="21.045444" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1992"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <radialGradient
+       r="0.8078171"
+       fy="6.9473476"
+       fx="4.8470273"
+       cy="6.9473476"
+       cx="4.8470273"
+       gradientTransform="matrix(3.018423,0.664359,-1.388844,4.257661,-0.134567,-26.02469)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient1990"
+       xlink:href="#linearGradient2898"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(1.076595,0,0,1.076595,-3.760351,-3.418494)"
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient1986"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(1.004822,0,0,1.004822,-2.476351,-2.157242)"
+       y2="36.603138"
+       x2="24.240097"
+       y1="9.4211226"
+       x1="15.498499"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient1983"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2898">
+      <stop
+         style="stop-color:white;stop-opacity:1;"
+         offset="0"
+         id="stop2900" />
+      <stop
+         style="stop-color:white;stop-opacity:0;"
+         offset="1"
+         id="stop2902" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient4738"
+       gradientUnits="userSpaceOnUse"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient4740"
+       gradientUnits="userSpaceOnUse"
+       x1="15.498499"
+       y1="9.4211226"
+       x2="24.240097"
+       y2="36.603138" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2269"
+       gradientUnits="userSpaceOnUse"
+       x1="17.890068"
+       y1="8.0617304"
+       x2="17.890068"
+       y2="40.032413" />
+    <linearGradient
+       id="linearGradient1935">
+      <stop
+         style="stop-color:#73d216;stop-opacity:1;"
+         offset="0"
+         id="stop1937" />
+      <stop
+         style="stop-color:#5ca911;stop-opacity:1;"
+         offset="1"
+         id="stop1939" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3816"
+       id="radialGradient1953"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.914124,-3.896132e-15,-2.475021e-18,1.631747,2.671799,-12.00863)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient1955"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2898"
+       id="radialGradient2904"
+       cx="4.8470273"
+       cy="6.9473476"
+       fx="4.8470273"
+       fy="6.9473476"
+       r="0.8078171"
+       gradientTransform="matrix(3.018423,0.664359,-1.388844,4.257661,-0.134567,-26.02469)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient2818"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="11.024895"
+       x2="10.623409"
+       y1="2.7991772"
+       x1="4.5264969"
+       id="linearGradient2810"
+       xlink:href="#linearGradient2804"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       id="linearGradient2963"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2951">
+      <stop
+         id="stop2953"
+         offset="0"
+         style="stop-color:#73d216;stop-opacity:1;" />
+      <stop
+         id="stop2955"
+         offset="1"
+         style="stop-color:#5ca911;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       y2="40.032413"
+       x2="17.890068"
+       y1="8.0617304"
+       x1="17.890068"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2949"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2804"
+       inkscape:collect="always">
+      <stop
+         id="stop2806"
+         offset="0"
+         style="stop-color:white;stop-opacity:1;" />
+      <stop
+         id="stop2808"
+         offset="1"
+         style="stop-color:white;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2812"
+       inkscape:collect="always">
+      <stop
+         id="stop2814"
+         offset="0"
+         style="stop-color:#2e3436;stop-opacity:1;" />
+      <stop
+         id="stop2816"
+         offset="1"
+         style="stop-color:#2e3436;stop-opacity:0;" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient3005"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2804"
+       id="linearGradient3007"
+       gradientUnits="userSpaceOnUse"
+       x1="4.5264969"
+       y1="2.7991772"
+       x2="10.623409"
+       y2="11.024895" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient3025"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="36.574547"
+       x2="17.890068"
+       y1="8.3091545"
+       x1="17.890068"
+       id="linearGradient3155"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient1983"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient3149"
+       inkscape:collect="always">
+      <stop
+         id="stop3151"
+         offset="0"
+         style="stop-color:#eeeeec;stop-opacity:1;" />
+      <stop
+         id="stop3153"
+         offset="1"
+         style="stop-color:#eeeeec;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2851">
+      <stop
+         id="stop2853"
+         offset="0"
+         style="stop-color:#73d216;stop-opacity:1;" />
+      <stop
+         id="stop2855"
+         offset="1"
+         style="stop-color:#5ca911;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2056"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.004822,0,0,1.004822,-33.47635,-2.157242)"
+       x1="15.498499"
+       y1="9.4211226"
+       x2="24.240097"
+       y2="36.603138" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient2059"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.076595,0,0,1.076595,-34.76035,-3.418494)"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient2062"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
   </defs>
   <sodipodi:namedview
      id="base"
@@ -119,16 +607,16 @@
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
      inkscape:zoom="16.976026"
-     inkscape:cx="19.582303"
-     inkscape:cy="17.200313"
+     inkscape:cx="12.808044"
+     inkscape:cy="15.904368"
      inkscape:document-units="px"
      inkscape:current-layer="layer1"
      showgrid="true"
      fill="#888a85"
-     inkscape:window-width="1268"
-     inkscape:window-height="971"
-     inkscape:window-x="6"
-     inkscape:window-y="23" />
+     inkscape:window-width="1440"
+     inkscape:window-height="849"
+     inkscape:window-x="0"
+     inkscape:window-y="0" />
   <metadata
      id="metadata7">
     <rdf:RDF>
@@ -145,6 +633,16 @@
      inkscape:groupmode="layer"
      id="layer1">
     <path
+       transform="matrix(1.731691,0,0,0.461784,-37.87759,19.22212)"
+       sodipodi:type="arc"
+       style="color:black;fill:url(#radialGradient2062);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       id="path2173"
+       sodipodi:cx="31.112698"
+       sodipodi:cy="19.008621"
+       sodipodi:rx="8.6620579"
+       sodipodi:ry="8.6620579"
+       d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1  22.45064,19.008621 A 8.6620579 8.6620579 0 1 1  39.774755 19.008621 z" />
+    <path
        d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1  22.45064,19.008621 A 8.6620579 8.6620579 0 1 1  39.774755 19.008621 z"
        sodipodi:ry="8.6620579"
        sodipodi:rx="8.6620579"
@@ -155,45 +653,26 @@
        sodipodi:type="arc"
        transform="matrix(1.847136,0,0,0.865845,-41.46938,8.041481)" />
     <path
-       sodipodi:type="arc"
-       style="opacity:1;fill:url(#radialGradient3156);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path3140"
-       sodipodi:cx="10.748654"
-       sodipodi:cy="10.457643"
-       sodipodi:rx="6.6449099"
-       sodipodi:ry="2.3675451"
-       d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1  4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1  17.393564 10.457643 z"
-       transform="matrix(2.182121,0,0,1.391928,-7.954869,12.14827)" />
-    <path
-       style="fill:#888a85;fill-opacity:1;stroke:#2e3436;stroke-width:0.99999875;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 26.256921,26.256907 C 20.600315,31.913529 11.419537,31.914486 5.7641107,26.259045 C 0.10868503,20.603602 0.1096427,11.422797 5.7662484,5.7661742 C 11.422853,0.1095522 20.603631,0.10859439 26.259058,5.7640366 C 31.914483,11.419479 31.913526,20.600284 26.256921,26.256907 z "
+       style="fill:#888a85;fill-opacity:1;stroke:#2e3436;stroke-width:0.99999887;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 26.107102,26.107103 C 20.250761,31.963443 10.74581,31.964434 4.8906904,26.109316 C -0.9644283,20.254196 -0.96343682,10.749245 4.8929036,4.8929035 C 10.749243,-0.96343684 20.254194,-0.96442847 26.109314,4.8906904 C 31.964432,10.74581 31.963442,20.250761 26.107102,26.107103 z "
        id="path2187" />
     <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-1.0137641"
-       inkscape:original="M 16 1.53125 C 12.290802 1.5316369 8.6095524 2.9529389 5.78125 5.78125 C 0.1246443 11.437873 0.094574465 20.594557 5.75 26.25 C 11.405426 31.905441 20.593393 31.906622 26.25 26.25 C 31.906605 20.593377 31.905425 11.405442 26.25 5.75 C 23.422286 2.9222789 19.709198 1.5308631 16 1.53125 z "
-       xlink:href="#path2187"
-       style="opacity:0.4;fill:url(#linearGradient2231);fill-opacity:1;stroke:#ffffff;stroke-width:0.99999809;stroke-miterlimit:4;stroke-opacity:1"
-       id="path2215"
-       inkscape:href="#path2187"
-       d="M 16,2.53125 C 12.549705,2.5316099 9.1373736,3.8626287 6.5,6.5 C 1.2289233,11.771071 1.2014746,20.26398 6.46875,25.53125 C 11.736026,30.798519 20.262813,30.799682 25.53125,25.53125 C 30.799686,20.262819 30.798523,11.736019 25.53125,6.46875 C 22.89972,3.837224 19.4556,2.5308896 16,2.53125 z " />
+       style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1.00000036;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 20.92264,5.5294893 L 15.440071,10.599712 L 10.134222,5.2349563 L 5.3520274,10.017152 L 10.598969,15.440813 L 5.6452582,20.865777 L 9.8972946,25.942506 L 15.322258,20.340822 L 20.894813,25.442125 L 25.618102,21.013369 L 20.222267,15.49972 L 25.469209,10.252778 L 20.92264,5.5294893 z "
+       id="path2233"
+       sodipodi:nodetypes="ccccccccccccc" />
     <path
-       style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1.00000036;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 20.689058,7.0625004 L 15.795555,11.956003 L 10.902052,7.0625004 L 6.5911096,11.373443 L 11.484612,16.266945 L 6.7076214,21.043936 L 11.018564,25.354879 L 15.795555,20.577888 L 20.543417,25.325751 L 24.85436,21.014808 L 20.106498,16.266945 L 25,11.373443 L 20.689058,7.0625004 z "
-       id="path2233" />
+       style="opacity:0.4;fill:url(#linearGradient2231);fill-opacity:1;stroke:white;stroke-width:0.99999809;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 15.5,1.5 C 11.919821,1.5003735 8.3615884,2.8884111 5.625,5.625 C 0.15534426,11.094657 0.15654704,19.906546 5.625,25.375 C 11.093454,30.843452 19.905345,30.844655 25.375,25.375 C 30.844655,19.905343 30.843452,11.093454 25.375,5.625 C 22.638996,2.8889961 19.07979,1.4996266 15.5,1.5 z "
+       id="path2215" />
     <path
        style="opacity:1;fill:url(#linearGradient2270);fill-opacity:1;stroke:#555753;stroke-width:1.00000036;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 20.999968,6.7515891 L 16.03118,11.543656 L 11.018644,6.7127252 L 6.7383758,11.020002 L 11.484612,16.031319 L 6.7076211,21.043936 L 11.018564,25.354879 L 16.028737,20.500159 L 20.97092,25.325751 L 25.242999,20.975944 L 20.534,16.033762 L 25.310911,11.101395 L 20.999968,6.7515891 z "
+       d="M 20.955744,5.3057668 L 15.428786,10.645198 L 10.208679,5.2643747 L 5.2971223,10.087479 L 10.587082,15.424797 L 5.3232778,20.999126 L 9.9729678,25.708323 L 15.426184,20.184349 L 20.92481,25.618393 L 25.650927,20.985618 L 20.223902,15.427399 L 25.723247,10.233074 L 20.955744,5.3057668 z "
        id="rect2204"
        sodipodi:nodetypes="ccccccccccccc" />
     <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-1.0009557"
-       inkscape:original="M 11.03125 6.71875 L 6.75 11.03125 L 11.5 16.03125 L 6.71875 21.03125 L 11.03125 25.34375 L 16.03125 20.5 L 20.96875 25.3125 L 25.25 20.96875 L 20.53125 16.03125 L 25.3125 11.09375 L 21 6.75 L 16.03125 11.53125 L 11.03125 6.71875 z "
-       xlink:href="#rect2204"
-       style="opacity:1;fill:none;fill-opacity:1;stroke:#e1e1e1;stroke-width:1.00000036;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path2268"
-       inkscape:href="#rect2204"
-       d="M 11.40625,8.5 L 8.53125,11.375 L 12.71875,15.5625 C 12.913242,15.751048 13.023019,16.010367 13.023019,16.28125 C 13.023019,16.552133 12.913242,16.811452 12.71875,17 L 8.65625,21.03125 L 11.53125,23.90625 L 15.5625,19.84375 C 15.751048,19.649258 16.010367,19.539481 16.28125,19.539481 C 16.552133,19.539481 16.811452,19.649258 17,19.84375 L 21.03125,23.875 L 23.90625,21 L 19.875,17 C 19.680508,16.811452 19.570731,16.552133 19.570731,16.28125 C 19.570731,16.010367 19.680508,15.751048 19.875,15.5625 L 24.0625,11.375 L 21.1875,8.5 L 17,12.6875 C 16.811452,12.881992 16.552133,12.991769 16.28125,12.991769 C 16.010367,12.991769 15.751048,12.881992 15.5625,12.6875 L 11.40625,8.5 z " />
+       style="fill:none;fill-opacity:1;stroke:#e1e1e1;stroke-width:1.00000036;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 10.21875,6.6875 L 6.75,10.09375 L 11.3125,14.71875 C 11.697174,15.10858 11.697174,15.73517 11.3125,16.125 L 6.6875,21 L 9.96875,24.28125 L 14.71875,19.46875 C 14.907298,19.274258 15.166617,19.164481 15.4375,19.164481 C 15.708383,19.164481 15.967702,19.274258 16.15625,19.46875 L 20.96875,24.21875 L 24.25,21 L 19.5,16.125 C 19.123854,15.726673 19.137781,15.099974 19.53125,14.71875 L 24.3125,10.1875 L 20.9375,6.71875 L 16.125,11.375 C 15.726673,11.751146 15.099974,11.737219 14.71875,11.34375 L 10.21875,6.6875 z "
+       id="path2268" />
   </g>
 </svg>
Binary file pidgin/pixmaps/toolbar/16/insert.png has changed
--- a/pidgin/pixmaps/tray/16/Makefile.am	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/tray/16/Makefile.am	Mon Jun 18 01:48:35 2007 +0000
@@ -6,6 +6,7 @@
 		tray-connecting.png \
 		tray-extended-away.png \
 		tray-message.png \
+		tray-new-im.png \
 		tray-offline.png \
 		tray-online.png
 
--- a/pidgin/pixmaps/tray/16/scalable/tray-away.svg	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/tray/16/scalable/tray-away.svg	Mon Jun 18 01:48:35 2007 +0000
@@ -14,7 +14,7 @@
    id="svg1872"
    sodipodi:version="0.32"
    inkscape:version="0.44.1"
-   sodipodi:docbase="/home/hbons/Desktop"
+   sodipodi:docbase="/home/hbons/Desktop/experiment/tray/16/scalable"
    sodipodi:docname="tray-away.svg">
   <defs
      id="defs1874">
@@ -549,37 +549,6 @@
          offset="1"
          style="stop-color:#eeeeec;stop-opacity:0;" />
     </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2781"
-       id="radialGradient3201"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(2,0,0,0.8,-13,-79.2)"
-       cx="1"
-       cy="44"
-       fx="1"
-       fy="44"
-       r="5" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2781"
-       id="radialGradient3203"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(2,0,0,0.8,36,8.8)"
-       cx="1"
-       cy="44"
-       fx="1"
-       fy="44"
-       r="5" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2804"
-       id="linearGradient3205"
-       gradientUnits="userSpaceOnUse"
-       x1="21.875"
-       y1="48.000977"
-       x2="21.875"
-       y2="40" />
     <linearGradient
        y2="14.895812"
        x2="11.802028"
@@ -780,58 +749,297 @@
          offset="1.0000000"
          style="stop-color:#e9e9e9;stop-opacity:1.0000000;" />
     </linearGradient>
-    <radialGradient
+    <linearGradient
        inkscape:collect="always"
-       xlink:href="#linearGradient2781"
-       id="radialGradient3398"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2046"
        gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(2,0,0,0.8,-13,-79.2)"
-       cx="1"
-       cy="44"
-       fx="1"
-       fy="44"
-       r="5" />
-    <radialGradient
+       x1="17.890068"
+       y1="8.0617304"
+       x2="17.890068"
+       y2="40.032413" />
+    <linearGradient
+       id="linearGradient2048">
+      <stop
+         style="stop-color:#73d216;stop-opacity:1;"
+         offset="0"
+         id="stop2050" />
+      <stop
+         style="stop-color:#5ca911;stop-opacity:1;"
+         offset="1"
+         id="stop2052" />
+    </linearGradient>
+    <linearGradient
        inkscape:collect="always"
-       xlink:href="#linearGradient2781"
-       id="radialGradient3400"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(2,0,0,0.8,36,8.8)"
-       cx="1"
-       cy="44"
-       fx="1"
-       fy="44"
-       r="5" />
+       xlink:href="#linearGradient2851"
+       id="linearGradient2060"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807"
+       gradientUnits="userSpaceOnUse" />
     <linearGradient
        inkscape:collect="always"
        xlink:href="#linearGradient2804"
-       id="linearGradient3402"
-       gradientUnits="userSpaceOnUse"
-       x1="21.875"
-       y1="48.000977"
-       x2="21.875"
-       y2="40" />
+       id="linearGradient2062"
+       x1="4.5264969"
+       y1="2.7991772"
+       x2="10.623409"
+       y2="11.024895"
+       gradientUnits="userSpaceOnUse" />
     <radialGradient
        inkscape:collect="always"
-       xlink:href="#linearGradient2260"
-       id="radialGradient3404"
+       xlink:href="#linearGradient2812"
+       id="radialGradient2064"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2812">
+      <stop
+         style="stop-color:#2e3436;stop-opacity:1;"
+         offset="0"
+         id="stop2814" />
+      <stop
+         style="stop-color:#2e3436;stop-opacity:0;"
+         offset="1"
+         id="stop2816" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2269"
+       gradientUnits="userSpaceOnUse"
+       x1="17.890068"
+       y1="8.0617304"
+       x2="17.890068"
+       y2="40.032413" />
+    <linearGradient
+       id="linearGradient2177">
+      <stop
+         style="stop-color:#73d216;stop-opacity:1;"
+         offset="0"
+         id="stop2179" />
+      <stop
+         style="stop-color:#5ca911;stop-opacity:1;"
+         offset="1"
+         id="stop2181" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3149">
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:1;"
+         offset="0"
+         id="stop3151" />
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:0;"
+         offset="1"
+         id="stop3153" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient2857"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       y2="14.895812"
+       x2="11.802028"
+       y1="1.9986149"
+       x1="11.802028"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient6606"
+       xlink:href="#linearGradient2225"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="48.674999"
+       x2="15.535398"
+       y1="1.8014067"
+       x1="15.535398"
+       gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2170"
+       xlink:href="#linearGradient2239"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="17.697369"
+       x2="11.226587"
+       y1="-5.4832759"
+       x1="11.226587"
+       gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2168"
+       xlink:href="#linearGradient2186"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="33.483475"
+       x2="15.522223"
+       y1="1.5657365"
+       x1="15.602553"
+       gradientTransform="matrix(0.371983,0,0,0.372254,2.539836,8.539528)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient1357"
+       xlink:href="#linearGradient2239"
+       inkscape:collect="always" />
+    <radialGradient
        gradientUnits="userSpaceOnUse"
        gradientTransform="matrix(1,0,0,0.626667,0,6.566431)"
-       cx="11.756953"
-       cy="17.588654"
+       r="6.3436799"
+       fy="17.588654"
        fx="11.756953"
-       fy="17.588654"
-       r="6.3436799" />
+       cy="17.588654"
+       cx="11.756953"
+       id="radialGradient2266"
+       xlink:href="#linearGradient2260"
+       inkscape:collect="always" />
+    <radialGradient
+       r="7.0034069"
+       fy="8.963316"
+       fx="9.9988937"
+       cy="8.963316"
+       cx="9.9988937"
+       gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.80154)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2158"
+       xlink:href="#linearGradient2200"
+       inkscape:collect="always" />
+    <radialGradient
+       r="7.0034069"
+       fy="8.963316"
+       fx="9.9988937"
+       cy="8.963316"
+       cx="9.9988937"
+       gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.83521)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2156"
+       xlink:href="#linearGradient2200"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient2148"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)"
+       gradientUnits="userSpaceOnUse"
+       y2="17.697369"
+       x2="11.226587"
+       y1="-5.4832759"
+       x1="11.226587"
+       id="linearGradient2134"
+       xlink:href="#linearGradient2186"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)"
+       gradientUnits="userSpaceOnUse"
+       y2="48.674999"
+       x2="15.535398"
+       y1="1.8014067"
+       x1="15.535398"
+       id="linearGradient2126"
+       xlink:href="#linearGradient2239"
+       inkscape:collect="always" />
+    <radialGradient
+       r="5"
+       fy="44"
+       fx="1"
+       cy="44"
+       cx="1"
+       gradientTransform="matrix(2,0,0,0.8,-13,-79.2)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2124"
+       xlink:href="#linearGradient2781"
+       inkscape:collect="always" />
+    <radialGradient
+       r="5"
+       fy="44"
+       fx="1"
+       cy="44"
+       cx="1"
+       gradientTransform="matrix(2,0,0,0.8,36,8.8)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2116"
+       xlink:href="#linearGradient2781"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="40"
+       x2="21.875"
+       y1="48.000977"
+       x1="21.875"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2114"
+       xlink:href="#linearGradient2804"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2106">
+      <stop
+         id="stop2108"
+         offset="0"
+         style="stop-color:black;stop-opacity:0;" />
+      <stop
+         style="stop-color:black;stop-opacity:1;"
+         offset="0.5"
+         id="stop2110" />
+      <stop
+         id="stop2112"
+         offset="1"
+         style="stop-color:black;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       y2="24.143761"
+       x2="27.273300"
+       y1="10.957423"
+       x1="35.003674"
+       gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2104"
+       xlink:href="#linearGradient29418"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2098">
+      <stop
+         id="stop2100"
+         offset="0.0000000"
+         style="stop-color:#f5f5f5;stop-opacity:1.0000000;" />
+      <stop
+         id="stop2102"
+         offset="1.0000000"
+         style="stop-color:#e9e9e9;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2989"
+       inkscape:collect="always">
+      <stop
+         id="stop2991"
+         offset="0"
+         style="stop-color:#eeeeec;stop-opacity:1;" />
+      <stop
+         id="stop2993"
+         offset="1"
+         style="stop-color:#eeeeec;stop-opacity:0;" />
+    </linearGradient>
     <linearGradient
        inkscape:collect="always"
-       xlink:href="#linearGradient2239"
-       id="linearGradient3409"
+       xlink:href="#linearGradient2989"
+       id="linearGradient2232"
        gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.296524,0,0,0.296522,5.75564,5.75564)"
-       x1="15.602553"
-       y1="1.5657365"
-       x2="15.522223"
-       y2="33.483475" />
+       x1="1.5769236"
+       y1="1.3319674"
+       x2="10.043059"
+       y2="10.018044" />
   </defs>
   <sodipodi:namedview
      id="base"
@@ -840,15 +1048,15 @@
      borderopacity="1.0"
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
-     inkscape:zoom="22.197802"
-     inkscape:cx="15.940485"
-     inkscape:cy="11.44958"
+     inkscape:zoom="44.395604"
+     inkscape:cx="14.075416"
+     inkscape:cy="6.2074085"
      inkscape:current-layer="layer1"
      showgrid="true"
      inkscape:grid-bbox="true"
      inkscape:document-units="px"
      inkscape:window-width="1440"
-     inkscape:window-height="853"
+     inkscape:window-height="849"
      inkscape:window-x="0"
      inkscape:window-y="0" />
   <metadata
@@ -903,90 +1111,6 @@
        d="M 9.2045414,1.5000001 C 9.3816286,1.5000001 9.4999957,1.6028844 9.4999957,1.7987807 L 9.4999957,7.3475646 C 9.4999957,7.543461 9.3816293,7.6463453 9.2045414,7.6463453 L 4.9999978,8.3220879 C 4.8242182,8.3232475 4.6547723,8.3838621 4.5227251,8.4928197 L 3.7045437,9.175747 L 3.7045437,9.0050151 C 3.7025982,8.6286041 3.3781242,8.3239148 2.9772712,8.3220879 L 1.7954537,7.6463453 C 1.6183665,7.6463453 1.4999993,7.5434596 1.4999993,7.3475646 L 1.4999993,1.7987807 C 1.4999993,1.6028846 1.6183665,1.5000001 1.7954537,1.5000001 L 9.2045414,1.5000001 z "
        id="path5807"
        sodipodi:nodetypes="cccccccccccccc" />
-    <g
-       id="g3183"
-       style="opacity:0.3"
-       transform="matrix(-0.340425,0,0,0.625,-11.6596,-23.99648)">
-      <rect
-         transform="scale(-1,-1)"
-         y="-48"
-         x="-11"
-         height="8"
-         width="10"
-         id="rect3185"
-         style="opacity:1;color:black;fill:url(#radialGradient3201);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <rect
-         y="40"
-         x="38"
-         height="8"
-         width="10"
-         id="rect3187"
-         style="opacity:1;color:black;fill:url(#radialGradient3203);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <rect
-         y="40"
-         x="11"
-         height="8"
-         width="27"
-         id="rect3189"
-         style="opacity:1;color:black;fill:url(#linearGradient3205);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-    </g>
-    <path
-       style="fill:#efefef;fill-opacity:1;fill-rule:evenodd;stroke:#787878;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M -14.90628,-7.496478 C -14.122201,-7.496478 -13.50003,-6.8637163 -13.50003,-6.058978 L -13.50003,2.066022 C -13.50003,2.87076 -14.1222,3.503522 -14.90628,3.503522 L -20.68753,3.503522 L -23.46878,5.941022 L -23.46878,3.503522 L -25.09378,3.503522 C -25.877859,3.503522 -26.500031,2.87076 -26.50003,2.066022 L -26.50003,-6.058978 C -26.50003,-6.8637163 -25.877859,-7.496478 -25.09378,-7.496478 L -14.90628,-7.496478 z "
-       id="path3192"
-       sodipodi:nodetypes="cccccccccccc" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-1.0047876"
-       inkscape:original="M 1.59375 0.5 C 0.990612 0.5 0.49999997 1.0124794 0.5 1.65625 L 0.5 8.34375 C 0.49999924 8.9875204 0.99061204 9.46875 1.59375 9.46875 L 2.46875 9.46875 L 2.46875 11.4375 L 5.25 9.46875 L 9.40625 9.46875 C 10.009388 9.46875 10.5 8.9875205 10.5 8.34375 L 10.5 1.65625 C 10.5 1.0124794 10.009387 0.50000001 9.40625 0.5 L 1.59375 0.5 z "
-       xlink:href="#path2221"
-       style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:white;stroke-width:1.19785893;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path3194"
-       inkscape:href="#path2221"
-       d="M 1.59375,1.5 C 1.5597829,1.5 1.5,1.5229727 1.5,1.65625 L 1.5,8.34375 C 1.4999998,8.4770255 1.5250763,8.46875 1.59375,8.46875 L 2.46875,8.46875 C 3.0199231,8.4714246 3.4660754,8.9175769 3.46875,9.46875 L 3.46875,9.5 L 4.65625,8.65625 C 4.8293233,8.532463 5.0372235,8.4668103 5.25,8.46875 L 9.40625,8.46875 C 9.4749239,8.46875 9.5,8.4770272 9.5,8.34375 L 9.5,1.65625 C 9.5,1.5229737 9.4402151,1.5 9.40625,1.5 L 1.59375,1.5 z "
-       transform="matrix(-0.834823,0,0,0.834823,13.43129,5.899303)" />
-    <g
-       id="g3378"
-       style="opacity:0.3"
-       transform="matrix(-0.340425,0,0,0.625,-6.6596,-33.99648)">
-      <rect
-         transform="scale(-1,-1)"
-         y="-48"
-         x="-11"
-         height="8"
-         width="10"
-         id="rect3380"
-         style="opacity:1;color:black;fill:url(#radialGradient3398);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <rect
-         y="40"
-         x="38"
-         height="8"
-         width="10"
-         id="rect3382"
-         style="opacity:1;color:black;fill:url(#radialGradient3400);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <rect
-         y="40"
-         x="11"
-         height="8"
-         width="27"
-         id="rect3384"
-         style="opacity:1;color:black;fill:url(#linearGradient3402);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-    </g>
-    <path
-       sodipodi:type="arc"
-       style="fill:url(#radialGradient3404);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.81530744;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path2234"
-       sodipodi:cx="11.756953"
-       sodipodi:cy="17.588654"
-       sodipodi:rx="6.3436799"
-       sodipodi:ry="3.9753728"
-       d="M 18.100633 17.588654 A 6.3436799 3.9753728 0 1 1  5.4132733,17.588654 A 6.3436799 3.9753728 0 1 1  18.100633 17.588654 z"
-       transform="matrix(-1.024642,0,0,0.754646,3.54664,-13.27321)" />
-    <path
-       style="fill:#efefef;fill-opacity:1;fill-rule:evenodd;stroke:#787878;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M -9.90628,-17.49648 C -9.1222007,-17.49648 -8.5000301,-16.863718 -8.50003,-16.05898 L -8.50003,-7.93398 C -8.50003,-7.129242 -9.1222003,-6.49648 -9.90628,-6.49648 L -15.68753,-6.49648 L -18.46878,-4.05898 L -18.46878,-6.49648 L -20.09378,-6.49648 C -20.877859,-6.49648 -21.500031,-7.129242 -21.50003,-7.93398 L -21.50003,-16.05898 C -21.50003,-16.863718 -20.877859,-17.49648 -20.09378,-17.49648 L -9.90628,-17.49648 z "
-       id="path3387"
-       sodipodi:nodetypes="cccccccccccc" />
     <path
        sodipodi:type="inkscape:offset"
        inkscape:radius="-1.0047876"
@@ -998,47 +1122,89 @@
        d="M 1.59375,1.5 C 1.5597829,1.5 1.5,1.5229727 1.5,1.65625 L 1.5,8.34375 C 1.4999998,8.4770255 1.5250763,8.46875 1.59375,8.46875 L 2.46875,8.46875 C 3.0199231,8.4714246 3.4660754,8.9175769 3.46875,9.46875 L 3.46875,9.5 L 4.65625,8.65625 C 4.8293233,8.532463 5.0372235,8.4668103 5.25,8.46875 L 9.40625,8.46875 C 9.4749239,8.46875 9.5,8.4770272 9.5,8.34375 L 9.5,1.65625 C 9.5,1.5229737 9.4402151,1.5 9.40625,1.5 L 1.59375,1.5 z "
        transform="matrix(-1,0,0,1,-3e-5,-19.99648)" />
     <path
-       sodipodi:type="arc"
-       style="color:black;fill:#729fcf;fill-opacity:1;fill-rule:evenodd;stroke:#204a87;stroke-width:2.86901665px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       id="path1339"
-       sodipodi:cx="15.590227"
-       sodipodi:cy="16.57217"
-       sodipodi:rx="14.345175"
-       sodipodi:ry="14.345175"
-       d="M 29.935402 16.57217 A 14.345175 14.345175 0 1 1  1.2450523,16.57217 A 14.345175 14.345175 0 1 1  29.935402 16.57217 z"
-       transform="matrix(0.348549,0,0,0.348549,5.066035,4.723779)" />
+       style="fill:#efefef;fill-opacity:1;fill-rule:evenodd;stroke:#787878;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 33.877402,-6.5000005 C 34.782108,-6.5000005 35.499998,-5.7936619 35.499998,-4.8953494 L 35.499998,4.174417 C 35.499998,5.07273 34.78211,5.491987 33.877402,5.491987 L 27.20673,5.491987 L 23.519125,8.212917 L 23.519125,5.491987 L 22.122596,5.491987 C 21.217889,5.491987 20.499999,5.07273 20.5,4.174417 L 20.5,-4.8953494 C 20.5,-5.7936619 21.217889,-6.5000005 22.122596,-6.5000005 L 33.877402,-6.5000005 z "
+       id="path2198"
+       sodipodi:nodetypes="cccccccccccc" />
+    <path
+       sodipodi:type="inkscape:offset"
+       inkscape:radius="-1.0047876"
+       inkscape:original="M 1.59375 0.5 C 0.990612 0.5 0.49999997 1.0124794 0.5 1.65625 L 0.5 8.34375 C 0.49999924 8.9875204 0.99061204 9.46875 1.59375 9.46875 L 2.46875 9.46875 L 2.46875 11.4375 L 5.25 9.46875 L 9.40625 9.46875 C 10.009388 9.46875 10.5 8.9875205 10.5 8.34375 L 10.5 1.65625 C 10.5 1.0124794 10.009387 0.50000001 9.40625 0.5 L 1.59375 0.5 z "
+       xlink:href="#path2221"
+       style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:white;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="path2200"
+       inkscape:href="#path2221"
+       d="M 1.59375,1.5 C 1.5597829,1.5 1.5,1.5229727 1.5,1.65625 L 1.5,8.34375 C 1.4999998,8.4770255 1.5250763,8.46875 1.59375,8.46875 L 2.46875,8.46875 C 3.0199231,8.4714246 3.4660754,8.9175769 3.46875,9.46875 L 3.46875,9.5 L 4.65625,8.65625 C 4.8293233,8.532463 5.0372235,8.4668103 5.25,8.46875 L 9.40625,8.46875 C 9.4749239,8.46875 9.5,8.4770272 9.5,8.34375 L 9.5,1.65625 C 9.5,1.5229737 9.4402151,1.5 9.40625,1.5 L 1.59375,1.5 z "
+       transform="translate(19,-8)" />
     <path
        sodipodi:type="arc"
-       style="color:black;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#204a87;stroke-width:4.78170681px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       id="path1341"
+       style="color:black;fill:#729fcf;fill-opacity:1;fill-rule:evenodd;stroke:#173867;stroke-width:2.86902547px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       id="path2069"
        sodipodi:cx="15.590227"
        sodipodi:cy="16.57217"
        sodipodi:rx="14.345175"
        sodipodi:ry="14.345175"
        d="M 29.935402 16.57217 A 14.345175 14.345175 0 1 1  1.2450523,16.57217 A 14.345175 14.345175 0 1 1  29.935402 16.57217 z"
-       transform="matrix(0.20913,0,0,0.20913,7.239621,7.034267)" />
+       transform="matrix(0.348549,0,0,0.348549,5.066037,4.723781)" />
+    <path
+       sodipodi:type="arc"
+       style="fill:#8ab0d7;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="path2788"
+       sodipodi:cx="-3.8088531"
+       sodipodi:cy="3.303823"
+       sodipodi:rx="3.1932809"
+       sodipodi:ry="3.3471739"
+       d="M -0.61557221 3.303823 A 3.1932809 3.3471739 0 1 1  -7.0021341,3.303823 A 3.1932809 3.3471739 0 1 1  -0.61557221 3.303823 z"
+       transform="matrix(1.409209,0,0,1.344418,15.86747,6.058282)" />
     <path
-       style="opacity:0.5;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3409);stroke-width:0.99999952px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
-       d="M 14.5,10.500004 C 14.5,12.708004 12.708,14.500005 10.499999,14.500005 C 8.2920005,14.500005 6.4999997,12.708004 6.4999997,10.500004 C 6.4999997,8.2920009 8.2920005,6.4999998 10.499999,6.4999998 C 12.708,6.4999998 14.5,8.2920009 14.5,10.500004 z "
-       id="path2220" />
+       sodipodi:type="arc"
+       style="fill:#dcdcd8;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="path2796"
+       sodipodi:cx="6.0403023"
+       sodipodi:cy="7.5551186"
+       sodipodi:rx="1.615877"
+       sodipodi:ry="1.3273276"
+       d="M 7.6561793 7.5551186 A 1.615877 1.3273276 0 1 1  4.4244252,7.5551186 A 1.615877 1.3273276 0 1 1  7.6561793 7.5551186 z"
+       transform="matrix(2.784865,0,0,3.390272,-6.321424,-15.11391)" />
     <rect
-       style="fill:#2e3436;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
-       id="rect3421"
+       style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2832"
        width="1"
-       height="3"
+       height="1"
        x="10"
-       y="8"
-       rx="0.5"
-       ry="0.5" />
+       y="-11"
+       transform="matrix(0,1,-1,0,0,0)" />
     <rect
-       style="fill:#2e3436;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
-       id="rect3423"
+       style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2236"
+       width="1"
+       height="1"
+       x="9"
+       y="-12"
+       transform="matrix(0,1,-1,0,0,0)" />
+    <rect
+       style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2240"
        width="1"
-       height="3"
-       x="10"
+       height="1"
+       x="11"
+       y="-12"
+       transform="matrix(0,1,-1,0,0,0)" />
+    <rect
+       style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect3133"
+       width="1"
+       height="1"
+       x="8"
        y="-13"
-       transform="matrix(0,1,-1,0,0,0)"
-       rx="0.5"
-       ry="0.5" />
+       transform="matrix(0,1,-1,0,0,0)" />
+    <rect
+       style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect3135"
+       width="1"
+       height="1"
+       x="12"
+       y="-13"
+       transform="matrix(0,1,-1,0,0,0)" />
   </g>
 </svg>
--- a/pidgin/pixmaps/tray/16/scalable/tray-online.svg	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/tray/16/scalable/tray-online.svg	Mon Jun 18 01:48:35 2007 +0000
@@ -14,7 +14,7 @@
    id="svg1872"
    sodipodi:version="0.32"
    inkscape:version="0.44.1"
-   sodipodi:docbase="/home/hbons/Desktop"
+   sodipodi:docbase="/home/hbons/Desktop/experiment/tray/16/scalable"
    sodipodi:docname="tray-online.svg">
   <defs
      id="defs1874">
@@ -150,6 +150,573 @@
        y1="48.000977"
        x2="21.875"
        y2="40" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2898">
+      <stop
+         style="stop-color:white;stop-opacity:1;"
+         offset="0"
+         id="stop2900" />
+      <stop
+         style="stop-color:white;stop-opacity:0;"
+         offset="1"
+         id="stop2902" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient4738"
+       gradientUnits="userSpaceOnUse"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient4740"
+       gradientUnits="userSpaceOnUse"
+       x1="15.498499"
+       y1="9.4211226"
+       x2="24.240097"
+       y2="36.603138" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient3044"
+       gradientUnits="userSpaceOnUse"
+       x1="17.890068"
+       y1="8.0617304"
+       x2="17.890068"
+       y2="40.032413" />
+    <linearGradient
+       id="linearGradient3046">
+      <stop
+         style="stop-color:#73d216;stop-opacity:1;"
+         offset="0"
+         id="stop3048" />
+      <stop
+         style="stop-color:#5ca911;stop-opacity:1;"
+         offset="1"
+         id="stop3050" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3816"
+       id="radialGradient3064"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.914124,-3.896132e-15,-2.475021e-18,1.631747,2.671799,-12.00863)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient3066"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2898"
+       id="radialGradient2904"
+       cx="4.8470273"
+       cy="6.9473476"
+       fx="4.8470273"
+       fy="6.9473476"
+       r="0.8078171"
+       gradientTransform="matrix(3.018423,0.664359,-1.388844,4.257661,-0.134567,-26.02469)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient2818"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="11.024895"
+       x2="10.623409"
+       y1="2.7991772"
+       x1="4.5264969"
+       id="linearGradient2810"
+       xlink:href="#linearGradient2804"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       id="linearGradient2963"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2951">
+      <stop
+         id="stop2953"
+         offset="0"
+         style="stop-color:#73d216;stop-opacity:1;" />
+      <stop
+         id="stop2955"
+         offset="1"
+         style="stop-color:#5ca911;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       y2="40.032413"
+       x2="17.890068"
+       y1="8.0617304"
+       x1="17.890068"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2949"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient3005"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2804"
+       id="linearGradient3007"
+       gradientUnits="userSpaceOnUse"
+       x1="4.5264969"
+       y1="2.7991772"
+       x2="10.623409"
+       y2="11.024895" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient3025"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="10.018044"
+       x2="10.043059"
+       y1="1.3319674"
+       x1="1.5769236"
+       id="linearGradient2995"
+       xlink:href="#linearGradient2989"
+       inkscape:collect="always" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2084"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2046"
+       gradientUnits="userSpaceOnUse"
+       x1="17.890068"
+       y1="8.0617304"
+       x2="17.890068"
+       y2="40.032413" />
+    <linearGradient
+       id="linearGradient2048">
+      <stop
+         style="stop-color:#73d216;stop-opacity:1;"
+         offset="0"
+         id="stop2050" />
+      <stop
+         style="stop-color:#5ca911;stop-opacity:1;"
+         offset="1"
+         id="stop2052" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient2060"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2804"
+       id="linearGradient2062"
+       x1="4.5264969"
+       y1="2.7991772"
+       x2="10.623409"
+       y2="11.024895"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient2064"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2812">
+      <stop
+         style="stop-color:#2e3436;stop-opacity:1;"
+         offset="0"
+         id="stop2814" />
+      <stop
+         style="stop-color:#2e3436;stop-opacity:0;"
+         offset="1"
+         id="stop2816" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2269"
+       gradientUnits="userSpaceOnUse"
+       x1="17.890068"
+       y1="8.0617304"
+       x2="17.890068"
+       y2="40.032413" />
+    <linearGradient
+       id="linearGradient2055">
+      <stop
+         style="stop-color:#73d216;stop-opacity:1;"
+         offset="0"
+         id="stop2057" />
+      <stop
+         style="stop-color:#5ca911;stop-opacity:1;"
+         offset="1"
+         id="stop2059" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient2857"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       y2="14.895812"
+       x2="11.802028"
+       y1="1.9986149"
+       x1="11.802028"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient6606"
+       xlink:href="#linearGradient2225"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="48.674999"
+       x2="15.535398"
+       y1="1.8014067"
+       x1="15.535398"
+       gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2339"
+       xlink:href="#linearGradient2239"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="17.697369"
+       x2="11.226587"
+       y1="-5.4832759"
+       x1="11.226587"
+       gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2337"
+       xlink:href="#linearGradient2186"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="33.483475"
+       x2="15.522223"
+       y1="1.5657365"
+       x1="15.602553"
+       gradientTransform="matrix(0.371983,0,0,0.372254,2.539836,8.539528)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient1357"
+       xlink:href="#linearGradient2239"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2239">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop2241" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop2243" />
+    </linearGradient>
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.626667,0,6.566431)"
+       r="6.3436799"
+       fy="17.588654"
+       fx="11.756953"
+       cy="17.588654"
+       cx="11.756953"
+       id="radialGradient2266"
+       xlink:href="#linearGradient2260"
+       inkscape:collect="always" />
+    <radialGradient
+       r="7.0034069"
+       fy="8.963316"
+       fx="9.9988937"
+       cy="8.963316"
+       cx="9.9988937"
+       gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.80154)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2225"
+       xlink:href="#linearGradient2200"
+       inkscape:collect="always" />
+    <radialGradient
+       r="7.0034069"
+       fy="8.963316"
+       fx="9.9988937"
+       cy="8.963316"
+       cx="9.9988937"
+       gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.83521)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2216"
+       xlink:href="#linearGradient2200"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2200"
+       inkscape:collect="always">
+      <stop
+         id="stop2202"
+         offset="0"
+         style="stop-color:#d3d7cf;stop-opacity:1;" />
+      <stop
+         id="stop2204"
+         offset="1"
+         style="stop-color:#d3d7cf;stop-opacity:0;" />
+    </linearGradient>
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient3822"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient3816"
+       inkscape:collect="always">
+      <stop
+         id="stop3818"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         id="stop3820"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2260"
+       inkscape:collect="always">
+      <stop
+         id="stop2262"
+         offset="0"
+         style="stop-color:#555753;stop-opacity:1;" />
+      <stop
+         id="stop2264"
+         offset="1"
+         style="stop-color:#555753;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)"
+       gradientUnits="userSpaceOnUse"
+       y2="17.697369"
+       x2="11.226587"
+       y1="-5.4832759"
+       x1="11.226587"
+       id="linearGradient2194"
+       xlink:href="#linearGradient2186"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2186"
+       inkscape:collect="always">
+      <stop
+         id="stop2188"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop2190"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)"
+       gradientUnits="userSpaceOnUse"
+       y2="48.674999"
+       x2="15.535398"
+       y1="1.8014067"
+       x1="15.535398"
+       id="linearGradient2245"
+       xlink:href="#linearGradient2239"
+       inkscape:collect="always" />
+    <radialGradient
+       r="5"
+       fy="44"
+       fx="1"
+       cy="44"
+       cx="1"
+       gradientTransform="matrix(2,0,0,0.8,-13,-79.2)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2827"
+       xlink:href="#linearGradient2781"
+       inkscape:collect="always" />
+    <radialGradient
+       r="5"
+       fy="44"
+       fx="1"
+       cy="44"
+       cx="1"
+       gradientTransform="matrix(2,0,0,0.8,36,8.8)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2829"
+       xlink:href="#linearGradient2781"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="40"
+       x2="21.875"
+       y1="48.000977"
+       x1="21.875"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2831"
+       xlink:href="#linearGradient2804"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2006">
+      <stop
+         id="stop2008"
+         offset="0"
+         style="stop-color:black;stop-opacity:0;" />
+      <stop
+         style="stop-color:black;stop-opacity:1;"
+         offset="0.5"
+         id="stop2010" />
+      <stop
+         id="stop2012"
+         offset="1"
+         style="stop-color:black;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       y2="24.143761"
+       x2="27.273300"
+       y1="10.957423"
+       x1="35.003674"
+       gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient29443"
+       xlink:href="#linearGradient29418"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient29418">
+      <stop
+         id="stop29420"
+         offset="0.0000000"
+         style="stop-color:#f5f5f5;stop-opacity:1.0000000;" />
+      <stop
+         id="stop29422"
+         offset="1.0000000"
+         style="stop-color:#e9e9e9;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2225"
+       inkscape:collect="always">
+      <stop
+         id="stop2227"
+         offset="0"
+         style="stop-color:#eeeeec;stop-opacity:1;" />
+      <stop
+         id="stop2229"
+         offset="1"
+         style="stop-color:#eeeeec;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2989"
+       inkscape:collect="always">
+      <stop
+         id="stop2991"
+         offset="0"
+         style="stop-color:#eeeeec;stop-opacity:1;" />
+      <stop
+         id="stop2993"
+         offset="1"
+         style="stop-color:#eeeeec;stop-opacity:0;" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient2112"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient2114"
+       gradientUnits="userSpaceOnUse"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2116"
+       gradientUnits="userSpaceOnUse"
+       x1="15.498499"
+       y1="9.4211226"
+       x2="24.240097"
+       y2="36.603138" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2119"
+       gradientUnits="userSpaceOnUse"
+       x1="15.498499"
+       y1="9.4211226"
+       x2="24.240097"
+       y2="36.603138"
+       gradientTransform="matrix(0.287092,0,0,0.287092,5.363901,5.455069)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient2122"
+       gradientUnits="userSpaceOnUse"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807"
+       gradientTransform="matrix(0.358865,0,0,0.358865,4.079883,4.193835)" />
   </defs>
   <sodipodi:namedview
      id="base"
@@ -159,14 +726,14 @@
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
      inkscape:zoom="22.197802"
-     inkscape:cx="24.938614"
-     inkscape:cy="9.7569307"
+     inkscape:cx="15.613366"
+     inkscape:cy="10.112799"
      inkscape:current-layer="layer1"
      showgrid="true"
      inkscape:grid-bbox="true"
      inkscape:document-units="px"
-     inkscape:window-width="1440"
-     inkscape:window-height="853"
+     inkscape:window-width="1434"
+     inkscape:window-height="844"
      inkscape:window-x="0"
      inkscape:window-y="0" />
   <metadata
@@ -222,12 +789,12 @@
        id="path5807"
        sodipodi:nodetypes="cccccccccccccc" />
     <path
-       style="fill:url(#linearGradient1959);fill-opacity:1;fill-rule:evenodd;stroke:#387101;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 15.541385,10.5 C 15.541385,13.26 13.292114,15.5 10.520692,15.5 C 7.7492697,15.5 5.4999993,13.26 5.4999993,10.5 C 5.4999993,7.7399998 7.7492697,5.5000001 10.520692,5.5000001 C 13.292114,5.5000001 15.541385,7.7399998 15.541385,10.5 z "
-       id="path2245" />
+       style="fill:url(#linearGradient2122);fill-opacity:1;fill-rule:evenodd;stroke:#306300;stroke-width:0.99999887;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 15.500002,10.5 C 15.500002,13.26 13.260001,15.5 10.500001,15.5 C 7.7400006,15.5 5.4999996,13.26 5.4999996,10.5 C 5.4999996,7.739999 7.7400006,5.4999989 10.500001,5.4999989 C 13.260001,5.4999989 15.500002,7.739999 15.500002,10.5 z "
+       id="path4331" />
     <path
-       style="opacity:0.6;fill:url(#linearGradient1956);fill-opacity:1;fill-rule:evenodd;stroke:white;stroke-width:1.00000024;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 14.500006,10.499996 C 14.500006,12.707996 12.708004,14.499996 10.500004,14.499996 C 8.2920042,14.499996 6.5000039,12.707996 6.5000039,10.499996 C 6.5000039,8.2919968 8.2920042,6.4999962 10.500004,6.4999962 C 12.708004,6.4999962 14.500006,8.2919968 14.500006,10.499996 z "
-       id="path3145" />
+       style="opacity:0.6;fill:url(#linearGradient2119);fill-opacity:1;fill-rule:evenodd;stroke:white;stroke-width:0.99999845;stroke-miterlimit:4;stroke-opacity:1"
+       d="M 14.500006,10.500002 C 14.500006,12.708002 12.708005,14.500003 10.500003,14.500003 C 8.2920011,14.500003 6.4999992,12.708002 6.4999992,10.500002 C 6.4999992,8.2920001 8.2920011,6.4999996 10.500003,6.4999996 C 12.708005,6.4999996 14.500006,8.2920001 14.500006,10.500002 z "
+       id="path4333" />
   </g>
 </svg>
Binary file pidgin/pixmaps/tray/16/tray-away.png has changed
Binary file pidgin/pixmaps/tray/16/tray-new-im.png has changed
Binary file pidgin/pixmaps/tray/16/tray-online.png has changed
--- a/pidgin/pixmaps/tray/22/Makefile.am	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/tray/22/Makefile.am	Mon Jun 18 01:48:35 2007 +0000
@@ -6,6 +6,7 @@
 		tray-extended-away.png \
 		tray-invisible.png \
 		tray-message.png \
+		tray-new-im.png \
 		tray-offline.png \
 		tray-online.png
 
--- a/pidgin/pixmaps/tray/22/scalable/tray-invisible.svg	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/tray/22/scalable/tray-invisible.svg	Mon Jun 18 01:48:35 2007 +0000
@@ -11,71 +11,62 @@
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    width="24"
    height="24"
-   id="svg4403"
+   id="svg2"
    sodipodi:version="0.32"
    inkscape:version="0.44.1"
    version="1.0"
-   sodipodi:docbase="/home/hbons/code/pidgin-mtn/pidgin/pixmaps/tray/22/scalable"
+   sodipodi:docbase="/home/hbons/Desktop"
    sodipodi:docname="tray-invisible.svg"
-   inkscape:export-filename="/home/hbons/code/pidgin-mtn/pidgin/pixmaps/tray/22/tray-invisible.png"
+   inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/notification-area/tray-busy.png"
    inkscape:export-xdpi="90"
    inkscape:export-ydpi="90">
   <defs
-     id="defs4405">
+     id="defs4">
     <linearGradient
-       id="linearGradient5187"
-       inkscape:collect="always">
+       inkscape:collect="always"
+       id="linearGradient2989">
       <stop
-         id="stop5189"
+         style="stop-color:#eeeeec;stop-opacity:1;"
          offset="0"
-         style="stop-color:#d3d7cf;stop-opacity:1;" />
+         id="stop2991" />
       <stop
-         id="stop5191"
+         style="stop-color:#eeeeec;stop-opacity:0;"
          offset="1"
-         style="stop-color:#d3d7cf;stop-opacity:0;" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient2851">
-      <stop
-         style="stop-color:#73d216;stop-opacity:1;"
-         offset="0"
-         id="stop2853" />
-      <stop
-         style="stop-color:#5ca911;stop-opacity:1;"
-         offset="1"
-         id="stop2855" />
+         id="stop2993" />
     </linearGradient>
     <linearGradient
        inkscape:collect="always"
-       xlink:href="#linearGradient2804"
-       id="linearGradient2261"
-       gradientUnits="userSpaceOnUse"
-       x1="21.875"
-       y1="48.000977"
-       x2="21.875"
-       y2="40" />
-    <radialGradient
+       id="linearGradient2225">
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:1;"
+         offset="0"
+         id="stop2227" />
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:0;"
+         offset="1"
+         id="stop2229" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient29418">
+      <stop
+         style="stop-color:#f5f5f5;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop29420" />
+      <stop
+         style="stop-color:#e9e9e9;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop29422" />
+    </linearGradient>
+    <linearGradient
        inkscape:collect="always"
-       xlink:href="#linearGradient2781"
-       id="radialGradient2259"
+       xlink:href="#linearGradient29418"
+       id="linearGradient29443"
        gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(2,0,0,0.8,36,8.8)"
-       cx="1"
-       cy="44"
-       fx="1"
-       fy="44"
-       r="5" />
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2781"
-       id="radialGradient2257"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(2,0,0,0.8,-13,-79.2)"
-       cx="1"
-       cy="44"
-       fx="1"
-       fy="44"
-       r="5" />
+       gradientTransform="matrix(-0.977228,0,0,0.995878,50.60272,9.115637)"
+       x1="35.003674"
+       y1="10.957423"
+       x2="27.273300"
+       y2="24.143761" />
     <linearGradient
        id="linearGradient2804">
       <stop
@@ -94,7 +85,7 @@
     <linearGradient
        inkscape:collect="always"
        xlink:href="#linearGradient2804"
-       id="linearGradient7755"
+       id="linearGradient2831"
        gradientUnits="userSpaceOnUse"
        x1="21.875"
        y1="48.000977"
@@ -103,7 +94,7 @@
     <radialGradient
        inkscape:collect="always"
        xlink:href="#linearGradient2781"
-       id="radialGradient7753"
+       id="radialGradient2829"
        gradientUnits="userSpaceOnUse"
        gradientTransform="matrix(2,0,0,0.8,36,8.8)"
        cx="1"
@@ -126,7 +117,7 @@
     <radialGradient
        inkscape:collect="always"
        xlink:href="#linearGradient2781"
-       id="radialGradient7751"
+       id="radialGradient2827"
        gradientUnits="userSpaceOnUse"
        gradientTransform="matrix(2,0,0,0.8,-13,-79.2)"
        cx="1"
@@ -136,14 +127,723 @@
        r="5" />
     <linearGradient
        inkscape:collect="always"
-       xlink:href="#linearGradient5187"
-       id="linearGradient2220"
+       id="linearGradient2186">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop2188" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop2190" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2260">
+      <stop
+         style="stop-color:#555753;stop-opacity:1;"
+         offset="0"
+         id="stop2262" />
+      <stop
+         style="stop-color:#555753;stop-opacity:0;"
+         offset="1"
+         id="stop2264" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3816">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop3818" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop3820" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3816"
+       id="radialGradient3822"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2200">
+      <stop
+         style="stop-color:#d3d7cf;stop-opacity:1;"
+         offset="0"
+         id="stop2202" />
+      <stop
+         style="stop-color:#d3d7cf;stop-opacity:0;"
+         offset="1"
+         id="stop2204" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2200"
+       id="radialGradient2216"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.83521)"
+       cx="9.9988937"
+       cy="8.963316"
+       fx="9.9988937"
+       fy="8.963316"
+       r="7.0034069" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2200"
+       id="radialGradient2225"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-2.522332,-1.518129e-16,-1.517788e-16,2.521765,40.1904,-21.80154)"
+       cx="9.9988937"
+       cy="8.963316"
+       fx="9.9988937"
+       fy="8.963316"
+       r="7.0034069" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2260"
+       id="radialGradient2266"
+       cx="11.756953"
+       cy="17.588654"
+       fx="11.756953"
+       fy="17.588654"
+       r="6.3436799"
+       gradientTransform="matrix(1,0,0,0.626667,0,6.566431)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient2239"
+       inkscape:collect="always">
+      <stop
+         id="stop2241"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop2243"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2239"
+       id="linearGradient1357"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.371983,0,0,0.372254,2.539836,8.539528)"
+       x1="15.602553"
+       y1="1.5657365"
+       x2="15.522223"
+       y2="33.483475" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2186"
+       id="linearGradient2337"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.529942,0,0,0.53199,17.26643,15.48536)"
+       x1="11.226587"
+       y1="-5.4832759"
+       x2="11.226587"
+       y2="17.697369" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2239"
+       id="linearGradient2339"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.37378,0,0,0.375227,17.64779,15.86312)"
+       x1="15.535398"
+       y1="1.8014067"
+       x2="15.535398"
+       y2="48.674999" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2225"
+       id="linearGradient6606"
+       gradientUnits="userSpaceOnUse"
+       x1="11.802028"
+       y1="1.9986149"
+       x2="11.802028"
+       y2="14.895812" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       id="linearGradient2857"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient3149"
+       inkscape:collect="always">
+      <stop
+         id="stop3151"
+         offset="0"
+         style="stop-color:#eeeeec;stop-opacity:1;" />
+      <stop
+         id="stop3153"
+         offset="1"
+         style="stop-color:#eeeeec;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2851">
+      <stop
+         id="stop2853"
+         offset="0"
+         style="stop-color:#73d216;stop-opacity:1;" />
+      <stop
+         id="stop2855"
+         offset="1"
+         style="stop-color:#5ca911;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       y2="40.032413"
+       x2="17.890068"
+       y1="8.0617304"
+       x1="17.890068"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2269"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2812"
+       inkscape:collect="always">
+      <stop
+         id="stop2814"
+         offset="0"
+         style="stop-color:#2e3436;stop-opacity:1;" />
+      <stop
+         id="stop2816"
+         offset="1"
+         style="stop-color:#2e3436;stop-opacity:0;" />
+    </linearGradient>
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient2064"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="11.024895"
+       x2="10.623409"
+       y1="2.7991772"
+       x1="4.5264969"
+       id="linearGradient2062"
+       xlink:href="#linearGradient2804"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       id="linearGradient2060"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2048">
+      <stop
+         id="stop2050"
+         offset="0"
+         style="stop-color:#73d216;stop-opacity:1;" />
+      <stop
+         id="stop2052"
+         offset="1"
+         style="stop-color:#5ca911;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       y2="40.032413"
+       x2="17.890068"
+       y1="8.0617304"
+       x1="17.890068"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2046"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient2084"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2989"
+       id="linearGradient2995"
+       x1="1.5769236"
+       y1="1.3319674"
+       x2="10.043059"
+       y2="10.018044"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient3025"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="11.024895"
+       x2="10.623409"
+       y1="2.7991772"
+       x1="4.5264969"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3007"
+       xlink:href="#linearGradient2804"
+       inkscape:collect="always" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient3005"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient2949"
+       gradientUnits="userSpaceOnUse"
+       x1="17.890068"
+       y1="8.0617304"
+       x2="17.890068"
+       y2="40.032413" />
+    <linearGradient
+       id="linearGradient2951">
+      <stop
+         style="stop-color:#73d216;stop-opacity:1;"
+         offset="0"
+         id="stop2953" />
+      <stop
+         style="stop-color:#5ca911;stop-opacity:1;"
+         offset="1"
+         id="stop2955" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient2963"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2804"
+       id="linearGradient2810"
+       x1="4.5264969"
+       y1="2.7991772"
+       x2="10.623409"
+       y2="11.024895"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient2818"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(3.018423,0.664359,-1.388844,4.257661,-0.134567,-26.02469)"
+       r="0.8078171"
+       fy="6.9473476"
+       fx="4.8470273"
+       cy="6.9473476"
+       cx="4.8470273"
+       id="radialGradient2904"
+       xlink:href="#linearGradient2898"
+       inkscape:collect="always" />
+    <linearGradient
        gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.394752,0,0,0.394752,8.437859,8.563225)"
-       x1="19.461548"
-       y1="6.4422231"
-       x2="19.461548"
-       y2="28.669207" />
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       id="linearGradient3066"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientTransform="matrix(0.914124,-3.896132e-15,-2.475021e-18,1.631747,2.671799,-12.00863)"
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient3064"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient3046">
+      <stop
+         id="stop3048"
+         offset="0"
+         style="stop-color:#73d216;stop-opacity:1;" />
+      <stop
+         id="stop3050"
+         offset="1"
+         style="stop-color:#5ca911;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       y2="40.032413"
+       x2="17.890068"
+       y1="8.0617304"
+       x1="17.890068"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3044"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="36.603138"
+       x2="24.240097"
+       y1="9.4211226"
+       x1="15.498499"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient4740"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2898"
+       inkscape:collect="always">
+      <stop
+         id="stop2900"
+         offset="0"
+         style="stop-color:white;stop-opacity:1;" />
+      <stop
+         id="stop2902"
+         offset="1"
+         style="stop-color:white;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       id="linearGradient2055"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientTransform="matrix(0.914124,-3.896132e-15,-2.475021e-18,1.631747,2.671799,-12.00863)"
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient2053"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient2034">
+      <stop
+         id="stop2036"
+         offset="0"
+         style="stop-color:#73d216;stop-opacity:1;" />
+      <stop
+         id="stop2038"
+         offset="1"
+         style="stop-color:#5ca911;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       y2="40.032413"
+       x2="17.890068"
+       y1="8.0617304"
+       x1="17.890068"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient2032"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(0.482882,0,0,0.482874,0.269812,0.26982)"
+       gradientUnits="userSpaceOnUse"
+       y2="39.834526"
+       x2="31.18539"
+       y1="4.5934086"
+       x1="8.7505674"
+       id="linearGradient2030"
+       xlink:href="#linearGradient2239"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(0.684526,0,0,0.687171,-0.20455,-0.253325)"
+       gradientUnits="userSpaceOnUse"
+       y2="17.697369"
+       x2="11.226587"
+       y1="-1.5641226"
+       x1="9.2594385"
+       id="linearGradient2022"
+       xlink:href="#linearGradient2186"
+       inkscape:collect="always" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2014"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(3.018423,0.664359,-1.388844,4.257661,-0.134567,-26.02469)"
+       r="0.8078171"
+       fy="6.9473476"
+       fx="4.8470273"
+       cy="6.9473476"
+       cx="4.8470273"
+       id="radialGradient2006"
+       xlink:href="#linearGradient2898"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       id="linearGradient3069"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientTransform="matrix(0.914124,-3.896132e-15,-2.475021e-18,1.631747,2.671799,-12.00863)"
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient3067"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient3049">
+      <stop
+         id="stop3051"
+         offset="0"
+         style="stop-color:#73d216;stop-opacity:1;" />
+      <stop
+         id="stop3053"
+         offset="1"
+         style="stop-color:#5ca911;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       y2="40.032413"
+       x2="17.890068"
+       y1="8.0617304"
+       x1="17.890068"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3047"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(0.482882,0,0,0.482874,0.269812,0.26982)"
+       gradientUnits="userSpaceOnUse"
+       y2="39.834526"
+       x2="31.18539"
+       y1="4.5934086"
+       x1="8.7505674"
+       id="linearGradient3045"
+       xlink:href="#linearGradient2239"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="matrix(0.684526,0,0,0.687171,-0.20455,-0.253325)"
+       gradientUnits="userSpaceOnUse"
+       y2="19.159578"
+       x2="14.441897"
+       y1="3.7276814"
+       x1="6.2538223"
+       id="linearGradient2194"
+       xlink:href="#linearGradient2186"
+       inkscape:collect="always" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient3030"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(3.018423,0.664359,-1.388844,4.257661,-0.134567,-26.02469)"
+       r="0.8078171"
+       fy="6.9473476"
+       fx="4.8470273"
+       cy="6.9473476"
+       cx="4.8470273"
+       id="radialGradient3022"
+       xlink:href="#linearGradient2898"
+       inkscape:collect="always" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient3082"
+       gradientUnits="userSpaceOnUse"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2239"
+       id="linearGradient3084"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.37378,0,0,0.375227,5.518529,18.82427)"
+       x1="15.535398"
+       y1="1.8014067"
+       x2="15.535398"
+       y2="48.674999" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient3198"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="11.024895"
+       x2="10.623409"
+       y1="2.7991772"
+       x1="4.5264969"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3196"
+       xlink:href="#linearGradient2804"
+       inkscape:collect="always" />
+    <radialGradient
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient3194"
+       xlink:href="#linearGradient2812"
+       inkscape:collect="always" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3149"
+       id="linearGradient3180"
+       gradientUnits="userSpaceOnUse"
+       x1="17.890068"
+       y1="8.0617304"
+       x2="17.890068"
+       y2="40.032413" />
+    <linearGradient
+       id="linearGradient3174">
+      <stop
+         style="stop-color:#73d216;stop-opacity:1;"
+         offset="0"
+         id="stop3176" />
+      <stop
+         style="stop-color:#5ca911;stop-opacity:1;"
+         offset="1"
+         id="stop3178" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2851"
+       id="linearGradient3172"
+       x1="6.878005"
+       y1="11.789385"
+       x2="12.233074"
+       y2="27.77807"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2804"
+       id="linearGradient3170"
+       x1="4.5264969"
+       y1="2.7991772"
+       x2="10.623409"
+       y2="11.024895"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2812"
+       id="radialGradient3168"
+       cx="31.112698"
+       cy="19.008621"
+       fx="31.112698"
+       fy="19.008621"
+       r="8.6620579"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="27.77807"
+       x2="12.233074"
+       y1="11.789385"
+       x1="6.878005"
+       id="linearGradient3166"
+       xlink:href="#linearGradient2851"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientTransform="matrix(0.914124,-3.896132e-15,-2.475021e-18,1.631747,2.671799,-12.00863)"
+       gradientUnits="userSpaceOnUse"
+       r="8.6620579"
+       fy="19.008621"
+       fx="31.112698"
+       cy="19.008621"
+       cx="31.112698"
+       id="radialGradient3164"
+       xlink:href="#linearGradient3816"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient3146">
+      <stop
+         id="stop3148"
+         offset="0"
+         style="stop-color:#73d216;stop-opacity:1;" />
+      <stop
+         id="stop3150"
+         offset="1"
+         style="stop-color:#5ca911;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       y2="40.032413"
+       x2="17.890068"
+       y1="8.0617304"
+       x1="17.890068"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3144"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="36.603138"
+       x2="24.240097"
+       y1="9.4211226"
+       x1="15.498499"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3142"
+       xlink:href="#linearGradient3149"
+       inkscape:collect="always" />
   </defs>
   <sodipodi:namedview
      id="base"
@@ -152,21 +852,19 @@
      borderopacity="1.0"
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
-     inkscape:zoom="25.498579"
-     inkscape:cx="19.883015"
-     inkscape:cy="11.999162"
+     inkscape:zoom="20.899939"
+     inkscape:cx="26.526463"
+     inkscape:cy="11.289944"
+     inkscape:document-units="px"
      inkscape:current-layer="layer1"
      showgrid="true"
-     inkscape:grid-bbox="true"
-     inkscape:document-units="px"
-     width="24px"
-     height="24px"
-     inkscape:window-width="1274"
-     inkscape:window-height="844"
-     inkscape:window-x="6"
+     fill="#d3d7cf"
+     inkscape:window-width="1440"
+     inkscape:window-height="849"
+     inkscape:window-x="0"
      inkscape:window-y="0" />
   <metadata
-     id="metadata4408">
+     id="metadata7">
     <rdf:RDF>
       <cc:Work
          rdf:about="">
@@ -177,53 +875,55 @@
     </rdf:RDF>
   </metadata>
   <g
-     id="layer1"
      inkscape:label="Layer 1"
-     inkscape:groupmode="layer">
+     inkscape:groupmode="layer"
+     id="layer1">
+    <path
+       style="opacity:1;fill:#efefef;fill-opacity:1;fill-rule:evenodd;stroke:#787878;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 14.877402,1.4999995 C 15.782108,1.4999995 16.499998,2.2063381 16.499998,3.1046506 L 16.499998,12.174417 C 16.499998,13.07273 15.78211,13.491987 14.877402,13.491987 L 8.2067299,13.491987 L 4.5191254,16.212917 L 4.5191254,13.491987 L 3.1225959,13.491987 C 2.2178895,13.491987 1.4999988,13.07273 1.5,12.174417 L 1.5,3.1046506 C 1.5,2.2063381 2.2178895,1.4999995 3.1225959,1.4999995 L 14.877402,1.4999995 z "
+       id="path2221"
+       sodipodi:nodetypes="cccccccccccc" />
+    <path
+       sodipodi:type="inkscape:offset"
+       inkscape:radius="-1.0047876"
+       inkscape:original="M 3.125 1.5 C 2.2202936 1.5 1.5 2.1954376 1.5 3.09375 L 1.5 12.1875 C 1.4999988 13.085813 2.2202937 13.5 3.125 13.5 L 4.53125 13.5 L 4.53125 16.21875 L 8.21875 13.5 L 14.875 13.5 C 15.779708 13.5 16.5 13.085813 16.5 12.1875 L 16.5 3.09375 C 16.5 2.1954375 15.779706 1.5 14.875 1.5 L 3.125 1.5 z "
+       xlink:href="#path2221"
+       style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:white;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="path5807"
+       inkscape:href="#path2221"
+       d="M 2.90625,2.5 C 2.6627552,2.5 2.5,2.6506524 2.5,2.9375 L 2.5,11.0625 C 2.4999996,11.349346 2.6627555,11.5 2.90625,11.5 L 4.53125,11.5 C 5.0824231,11.502675 5.5285754,11.948827 5.53125,12.5 L 5.53125,12.75 L 6.65625,11.75 C 6.8378154,11.590455 7.0708028,11.501698 7.3125,11.5 L 13.09375,11.5 C 13.337246,11.5 13.5,11.349348 13.5,11.0625 L 13.5,2.9375 C 13.5,2.6506524 13.337245,2.5 13.09375,2.5 L 2.90625,2.5 z " />
+    <g
+       id="g2057"
+       inkscape:label="Layer 1"
+       transform="translate(19.12926,4.037634)" />
     <g
-       id="g2249"
-       style="opacity:0.3"
-       transform="matrix(-0.340425,0,0,0.625,17.34043,-14)">
-      <rect
-         transform="scale(-1,-1)"
-         y="-48"
-         x="-11"
-         height="8"
-         width="10"
-         id="rect2251"
-         style="opacity:1;color:black;fill:url(#radialGradient2257);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <rect
-         y="40"
-         x="38"
-         height="8"
-         width="10"
-         id="rect2253"
-         style="opacity:1;color:black;fill:url(#radialGradient2259);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
-      <rect
-         y="40"
-         x="11"
-         height="8"
-         width="27"
-         id="rect2255"
-         style="opacity:1;color:black;fill:url(#linearGradient2261);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+       id="g3200"
+       inkscape:label="Layer 1"
+       transform="translate(6.999999,7.000001)">
+      <g
+         style="opacity:0.8"
+         id="g1918">
+        <path
+           d="M 39.774755 19.008621 A 8.6620579 8.6620579 0 1 1  22.45064,19.008621 A 8.6620579 8.6620579 0 1 1  39.774755 19.008621 z"
+           sodipodi:ry="8.6620579"
+           sodipodi:rx="8.6620579"
+           sodipodi:cy="19.008621"
+           sodipodi:cx="31.112698"
+           id="path3203"
+           style="color:black;fill:url(#radialGradient3025);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+           sodipodi:type="arc"
+           transform="matrix(0.923568,0,0,0.173169,-20.73469,11.2083)" />
+        <path
+           transform="matrix(0.538297,0,0,0.538297,-1.630177,-1.459246)"
+           style="fill:#babdb6;fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:1.85770929;stroke-miterlimit:4;stroke-opacity:1"
+           d="M 31.822886,17.572527 C 31.822886,25.263442 25.580983,31.505344 17.890068,31.505344 C 10.199153,31.505344 3.9572506,25.263442 3.9572506,17.572527 C 3.9572506,9.8816117 10.199153,3.6397095 17.890068,3.6397095 C 25.580983,3.6397095 31.822886,9.8816117 31.822886,17.572527 z "
+           id="path4331" />
+        <path
+           transform="matrix(0.466524,0,0,0.466525,-0.346154,-0.198015)"
+           style="opacity:0.6;fill:url(#linearGradient4740);fill-opacity:1;fill-rule:evenodd;stroke:white;stroke-width:2.14350748;stroke-miterlimit:4;stroke-opacity:1"
+           d="M 31.822886,17.572527 C 31.822886,25.263442 25.580983,31.505344 17.890068,31.505344 C 10.199153,31.505344 3.9572506,25.263442 3.9572506,17.572527 C 3.9572506,9.8816117 10.199153,3.6397095 17.890068,3.6397095 C 25.580983,3.6397095 31.822886,9.8816117 31.822886,17.572527 z "
+           id="path4333" />
+      </g>
     </g>
-    <path
-       style="fill:#efefef;fill-opacity:1;fill-rule:evenodd;stroke:#787878;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 9.90625,2.5 C 9.1221707,2.5 8.5000001,3.1327617 8.5,3.9375 L 8.5,12.0625 C 8.5,12.867238 9.1221703,13.5 9.90625,13.5 L 15.6875,13.5 L 18.46875,15.9375 L 18.46875,13.5 L 20.09375,13.5 C 20.877829,13.5 21.500001,12.867238 21.5,12.0625 L 21.5,3.9375 C 21.5,3.1327617 20.877829,2.5 20.09375,2.5 L 9.90625,2.5 z "
-       id="path2221"
-       transform="matrix(-1,0,0,1,24,0)" />
-    <path
-       style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:white;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 9.90625,3.5 C 9.6627547,3.5 9.5,3.650652 9.5,3.9375 L 9.5,12.0625 C 9.5,12.349348 9.6627543,12.5 9.90625,12.5 L 15.6875,12.5 C 15.929197,12.501698 16.162185,12.590455 16.34375,12.75 L 17.46875,13.75 L 17.46875,13.5 C 17.471425,12.948827 17.917577,12.502675 18.46875,12.5 L 20.09375,12.5 C 20.337245,12.5 20.5,12.349346 20.5,12.0625 L 20.5,3.9375 C 20.5,3.6506524 20.337245,3.5 20.09375,3.5 L 9.90625,3.5 z "
-       id="path5807"
-       transform="matrix(-1,0,0,1,24,0)" />
-    <path
-       style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#babdb6;stroke-width:0.99999863;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 21.500007,15.500001 C 21.500007,18.812 18.81201,21.499999 15.500004,21.499999 C 12.188,21.499999 9.5000032,18.812 9.5000032,15.500001 C 9.5000032,12.188001 12.188,9.5000014 15.500004,9.5000014 C 18.81201,9.5000014 21.500007,12.188001 21.500007,15.500001 z "
-       id="path4331" />
-    <path
-       style="opacity:0.6;fill:url(#linearGradient2220);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.14350748;stroke-miterlimit:4;stroke-opacity:1"
-       d="M 21,15.500001 C 21,18.536 18.535999,21 15.499999,21 C 12.464,21 10,18.536 10,15.500001 C 10,12.464 12.464,10 15.499999,10 C 18.535999,10 21,12.464 21,15.500001 z "
-       id="path4333" />
   </g>
 </svg>
Binary file pidgin/pixmaps/tray/22/tray-away.png has changed
Binary file pidgin/pixmaps/tray/22/tray-busy.png has changed
Binary file pidgin/pixmaps/tray/22/tray-connecting.png has changed
Binary file pidgin/pixmaps/tray/22/tray-extended-away.png has changed
Binary file pidgin/pixmaps/tray/22/tray-invisible.png has changed
Binary file pidgin/pixmaps/tray/22/tray-message.png has changed
Binary file pidgin/pixmaps/tray/22/tray-new-im.png has changed
Binary file pidgin/pixmaps/tray/22/tray-offline.png has changed
Binary file pidgin/pixmaps/tray/22/tray-online.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pixmaps/tray/32/Makefile.am	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,13 @@
+TRAY_ICONS =	tray-away.png \
+		tray-busy.png \
+		tray-connecting.png \
+		tray-extended-away.png \
+		tray-invisible.png \
+		tray-new-im.png \
+		tray-offline.png \
+		tray-online.png
+
+EXTRA_DIST =	$(TRAY_ICONS)
+
+pidgintraypixdir = $(datadir)/pixmaps/pidgin/tray/32
+pidgintraypix_DATA = $(TRAY_ICONS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pixmaps/tray/32/Makefile.mingw	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,20 @@
+#
+# Makefile.mingw
+#
+# Description: Makefile for win32 (mingw) version of Pidgin pixmaps
+#
+
+PIDGIN_TREE_TOP := ../../../..
+include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+
+datadir = $(PIDGIN_INSTALL_DIR)
+include ./Makefile.am
+
+.PHONY: install
+
+install:
+	if test '$(pidgintraypix_DATA)'; then \
+	  mkdir -p $(pidgintraypixdir); \
+	  cp $(pidgintraypix_DATA) $(pidgintraypixdir); \
+	fi;
+
Binary file pidgin/pixmaps/tray/32/tray-away.png has changed
Binary file pidgin/pixmaps/tray/32/tray-busy.png has changed
Binary file pidgin/pixmaps/tray/32/tray-connecting.png has changed
Binary file pidgin/pixmaps/tray/32/tray-extended-away.png has changed
Binary file pidgin/pixmaps/tray/32/tray-invisible.png has changed
Binary file pidgin/pixmaps/tray/32/tray-message.png has changed
Binary file pidgin/pixmaps/tray/32/tray-new-im.png has changed
Binary file pidgin/pixmaps/tray/32/tray-offline.png has changed
Binary file pidgin/pixmaps/tray/32/tray-online.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pixmaps/tray/48/Makefile.am	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,13 @@
+TRAY_ICONS =	tray-away.png \
+		tray-busy.png \
+		tray-connecting.png \
+		tray-extended-away.png \
+		tray-invisible.png \
+		tray-new-im.png \
+		tray-offline.png \
+		tray-online.png
+
+EXTRA_DIST =	$(TRAY_ICONS)
+
+pidgintraypixdir = $(datadir)/pixmaps/pidgin/tray/48
+pidgintraypix_DATA = $(TRAY_ICONS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pixmaps/tray/48/Makefile.mingw	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,20 @@
+#
+# Makefile.mingw
+#
+# Description: Makefile for win32 (mingw) version of Pidgin pixmaps
+#
+
+PIDGIN_TREE_TOP := ../../../..
+include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+
+datadir = $(PIDGIN_INSTALL_DIR)
+include ./Makefile.am
+
+.PHONY: install
+
+install:
+	if test '$(pidgintraypix_DATA)'; then \
+	  mkdir -p $(pidgintraypixdir); \
+	  cp $(pidgintraypix_DATA) $(pidgintraypixdir); \
+	fi;
+
Binary file pidgin/pixmaps/tray/48/tray-away.png has changed
Binary file pidgin/pixmaps/tray/48/tray-busy.png has changed
Binary file pidgin/pixmaps/tray/48/tray-connecting.png has changed
Binary file pidgin/pixmaps/tray/48/tray-extended-away.png has changed
Binary file pidgin/pixmaps/tray/48/tray-invisible.png has changed
Binary file pidgin/pixmaps/tray/48/tray-message.png has changed
Binary file pidgin/pixmaps/tray/48/tray-new-im.png has changed
Binary file pidgin/pixmaps/tray/48/tray-offline.png has changed
Binary file pidgin/pixmaps/tray/48/tray-online.png has changed
--- a/pidgin/pixmaps/tray/Makefile.am	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/pixmaps/tray/Makefile.am	Mon Jun 18 01:48:35 2007 +0000
@@ -1,7 +1,9 @@
-SUBDIRS = 16 22
+SUBDIRS = 16 22 32 48
 
 EXTRA_DIST = \
 	Makefile.mingw \
 	16/Makefile.mingw \
-	22/Makefile.mingw
+	22/Makefile.mingw \
+	32/Makefile.mingw \
+	48/Makefile.mingw
 
--- a/pidgin/plugins/Makefile.am	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/plugins/Makefile.am	Mon Jun 18 01:48:35 2007 +0000
@@ -30,6 +30,7 @@
 contact_priority_la_LDFLAGS = -module -avoid-version
 extplacement_la_LDFLAGS     = -module -avoid-version
 gtk_signals_test_la_LDFLAGS = -module -avoid-version
+gtkbuddynote_la_LDFLAGS     = -module -avoid-version
 history_la_LDFLAGS          = -module -avoid-version
 iconaway_la_LDFLAGS         = -module -avoid-version
 markerline_la_LDFLAGS       = -module -avoid-version
@@ -46,6 +47,7 @@
 plugin_LTLIBRARIES = \
 	convcolors.la       \
 	extplacement.la     \
+	gtkbuddynote.la     \
 	history.la          \
 	iconaway.la         \
 	markerline.la       \
@@ -65,6 +67,7 @@
 contact_priority_la_SOURCES = contact_priority.c
 extplacement_la_SOURCES     = extplacement.c
 gtk_signals_test_la_SOURCES = gtk-signals-test.c
+gtkbuddynote_la_SOURCES     = gtkbuddynote.c
 history_la_SOURCES          = history.c
 iconaway_la_SOURCES         = iconaway.c
 markerline_la_SOURCES       = markerline.c
@@ -80,6 +83,7 @@
 contact_priority_la_LIBADD  = $(GTK_LIBS)
 extplacement_la_LIBADD      = $(GTK_LIBS)
 gtk_signals_test_la_LIBADD  = $(GTK_LIBS)
+gtkbuddynote_la_LIBADD      = $(GTK_LIBS)
 history_la_LIBADD           = $(GTK_LIBS)
 iconaway_la_LIBADD          = $(GTK_LIBS)
 markerline_la_LIBADD        = $(GTK_LIBS)
--- a/pidgin/plugins/Makefile.mingw	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/plugins/Makefile.mingw	Mon Jun 18 01:48:35 2007 +0000
@@ -77,11 +77,12 @@
 plugins: \
 		convcolors.dll \
 		extplacement.dll \
-		pidginrc.dll \
+		gtkbuddynote.dll \
 		history.dll \
 		iconaway.dll \
 		markerline.dll \
 		notify.dll \
+		pidginrc.dll \
 		relnot.dll \
 		spellchk.dll \
 		timestamp_format.dll \
--- a/pidgin/plugins/gevolution/gevolution.c	Thu Jun 14 19:48:48 2007 +0000
+++ b/pidgin/plugins/gevolution/gevolution.c	Mon Jun 18 01:48:35 2007 +0000
@@ -38,7 +38,6 @@
 
 #include <libedata-book/Evolution-DataServer-Addressbook.h>
 
-#include <libebook/e-book-listener.h>
 #include <libedata-book/e-data-book-factory.h>
 #include <bonobo/bonobo-main.h>
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/plugins/gtkbuddynote.c	Mon Jun 18 01:48:35 2007 +0000
@@ -0,0 +1,126 @@
+/*
+ * GtkBuddyNote - Store notes on particular buddies
+ * Copyright (C) 2007 Etan Reisner <deryni@pidgin.im>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include "internal.h"
+
+#include <gtkblist.h>
+#include <gtkplugin.h>
+
+#include <debug.h>
+#include <version.h>
+
+static void
+append_to_tooltip(PurpleBlistNode *node, GString *text, gboolean full)
+{
+	if (full) {
+		const gchar *note = purple_blist_node_get_string(node, "notes");
+
+		if (note != NULL) {
+			g_string_append_printf(text, _("\nBuddy Note: %s"),
+			                       note);
+		}
+	}
+}
+
+static gboolean
+plugin_load(PurplePlugin *plugin)
+{
+	purple_signal_connect(pidgin_blist_get_handle(), "drawing-tooltip",
+	                      plugin, PURPLE_CALLBACK(append_to_tooltip), NULL);
+	return TRUE;
+}
+
+static gboolean
+plugin_unload(PurplePlugin *plugin)
+{
+	PurplePlugin *buddynote = NULL;
+
+	buddynote = purple_plugins_find_with_id("core-plugin_pack-buddynote");
+
+	purple_plugin_unload(buddynote);
+
+	return TRUE;
+}
+
+static PurplePluginInfo info =
+{
+	PURPLE_PLUGIN_MAGIC,
+	PURPLE_MAJOR_VERSION,                           /**< major version */
+	PURPLE_MINOR_VERSION,                           /**< minor version */
+	PURPLE_PLUGIN_STANDARD,                         /**< type */
+	PIDGIN_PLUGIN_TYPE,                             /**< ui_requirement */
+	0,                                              /**< flags */
+	NULL,                                           /**< dependencies */
+	PURPLE_PRIORITY_DEFAULT,                        /**< priority */